下标表示法和指针取消引用之间的等价性
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);
一般来说,N
行M
列的矩阵语法如下:
int (*matrix)[M] = malloc(N * sizeof *matrixA);
请注意,M
和 N
都不必作为常量表达式给出(感谢 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 版本中更好。但是我想你会发现这方法效果最好。
不止一题。我需要处理 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);
一般来说,N
行M
列的矩阵语法如下:
int (*matrix)[M] = malloc(N * sizeof *matrixA);
请注意,M
和 N
都不必作为常量表达式给出(感谢 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 版本中更好。但是我想你会发现这方法效果最好。