下标表示法和指针取消引用之间的等价性

Equivalence between Subscript Notation and Pointer Dereferencing

不止一题。我需要处理 C 中整数的 NxN 矩阵 A。如何分配堆中的内存?这个对吗?

int **A=malloc(N*sizeof(int*));
for(int i=0;i<N;i++) *(A+i)= malloc(N*sizeof(int));

我不确定上面代码的第二行是否应该在那里启动内存。

接下来,假设我要访问元素 A[i, j],其中 i 和 j 是从零开始的行和列索引。是否可以通过以某种方式取消引用指针 **A 来做到这一点?例如,像 (A+ni+j) 这样的东西?我知道我在这里有一些概念上的差距,一些帮助将不胜感激。

声明正确,但矩阵不会占用连续内存space。它是指针数组,其中每个指针都可以指向 malloc 返回的任何位置。出于这个原因,像 (A+ni+j) 这样的地址是没有意义的。

假设编译器支持 VLA(在 C11 中成为可选),定义连续矩阵的惯用方法是:

int (*matrixA)[N] = malloc(N * sizeof *matrixA);

一般来说,NM列的矩阵语法如下:

 int (*matrix)[M] = malloc(N * sizeof *matrixA);

请注意,MN 都不必作为常量表达式给出(感谢 VLA 指针)。也就是说,它们可以是普通(例如自动)变量。

然后,要访问元素,您可以使用普通的索引语法,如:

matrixA[0][0] = 100;

最后,要释放此类矩阵的内存,请使用单个 free,例如:

free(matrixA);
free(matrix);

not absolutely sure if the second line of the above code should be there to initiate the memory.

它需要在那里,因为它实际上为 N 行分配了 space,每个行都包含您需要的 N int

第一次分配只分配行索引指针。

to access the element A[i, j] where i and j are the row and column indices starting from zero. It it possible to do it via dereferencing the pointer **

当然可以,就这样

A[1][1] 

访问第 2 行的第 2 个元素。

这与

相同
*(*(A + 1) + 1)

与您的问题无关:

虽然您显示的代码是正确的,但更可靠的编码方式是:

int ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; i++) 
{
  A[i] = malloc(N * sizeof *A[i]);
}

size_t 是索引的选择类型,因为它保证足够大以容纳编译代码的系统可能的任何索引值。

您还想在 malloc() 的两个调用中添加错误检查,因为它可能 return NULL 以防失败分配请求的内存量。

您需要了解二维和更高级别的数组在 C 89 中效果不佳。初学者书籍通常在一维数组之后的很早的章节中介绍二维数组,这导致人们假设表示的自然方式二维数据是通过二维数组。事实上,它们有很多棘手的特性,应该被认为是一个高级特性。

如果您在编译时不知道数组维度,或者如果数组很大,分配一维数组并通过逻辑访问几乎总是更容易

array[y*width+x];

所以在你的情况下,只需调用

int *A;
A  = malloc(N * N * sizeof(int))
A[3*N+2] = 123; // set element A[3][2] to 123, but you can't use this      syntax

重要的是要注意使用平面数组的建议只是一个建议,并不是每个人都会同意,而且二维数组处理在以后的 C 版本中更好。但是我想你会发现这方法效果最好。