下标表示法与指针解除引用之间的等价性

时间:2016-10-02 10:09:44

标签: c pointers multidimensional-array malloc dereference

这不止一个问题。我需要处理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 + n i + j)?我知道我在这里有一些概念上的差距,一些帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

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

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

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

通常,N行和M列的矩阵语法如下:

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

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

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

matrixA[0][0] = 100;

最后,要为这些矩阵重新计算内存,请使用单free,例如:

free(matrixA);
free(matrix);

答案 1 :(得分:2)

  

不完全确定上面代码的第二行是否应该用于启动内存。

它需要存在,因为它实际上为您需要的N N行分配int行的空间。

第一个分配仅分配行索引指针。

  

访问元素A [i,j],其中i和j是从零开始的行和列索引。它可以通过取消引用指针**

来实现

当然,只是做

A[1][1] 

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

这与

相同
*(*(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()的两个调用添加错误检查,因为如果未能分配请求的内存量,它可能会返回NULL。< / p>

答案 2 :(得分:1)

你需要了解2D和更高的数组在C 89中不能很好地工作。初学者书籍通常在一个很早的章节中引入2D数组,就在1D数组之后,这导致人们假设代表2-的自然方式尺寸数据是通过2D阵列。事实上,它们有许多棘手的特征,应该被认为是一种高级功能。

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

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版本中2D阵列处理更好。但是我想你会发现这个方法有效最好的。