多维数组的指针如何在C中工作
我在C中尝试指向多维数组的概念。假设我想通过函数处理多维数组。 代码有点像这样:
#include void proc_arr(int ***array) { // some code } int main(int argc, char **argv) { int array[10][10]; for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { array[i][j] = i * j; } } proc_arr(&array); return 0; }
问题是,当我想访问proc_arr
array
,我不能。 根据我的理解,我们应该这样访问它:
void proc_arr(int ***array) { (*array)[0][1] = 10; }
所以我要求array
告诉编译器我想去那个地址并获取值。 但不知何故,它崩溃了。 我已经尝试了几种*
和括号的组合,仍然无法使其工作。 我很确定这是因为我不理解指针和指针指针。
哦,我注意到如果我们使用char **
(字符串数组)也是不同的,就像argv和envp一样。 但是对于envp,我可以用(*envp)
访问它。 为什么?
这是促使envp(和工作)的函数:
int envplen(char ***envp) { int count = 0; while((*envp)[count] != NULL) { count++; } return count; }
另外,我可以以envp
在envplen
函数中以某种方式访问envp
,但仍然通过引用传递它吗?
谢谢你。
问题是因为在堆栈上分配的int array[10][10]
没有像你想象的那样布局内存。 这是因为数组不是指针 。 内存仍然以线性数组布局,而不是“二维”数组,即使这是下标可能指示的内容。 换句话说, int array[10][10]
的内存如下所示:
starting address: ending address: | Block_1 of 10 int | Block_2 of 10 int | ... | Block_10 of 10 int |
所以当你隐式地将数组转换为int***
,然后尝试像(* array)[1] [10]那样访问数组时,这实际上转换为*(*((*array) + 1) + 10)
,这种操作的内存布局想要看到如下内存设置:
int*** array | | | Pointer | | | | Pointer_0 | Pointer_1 | ... | Pointer 10 | | | | | | | Block of 10 int | | | | | Block of 10 int | | |Block of 10 int|
您的类型不匹配。 给定int array[10][10]
,表达式&array
的类型将是int (*)[10][10]
, 而不是 int ***
。 如果你改变你的函数原型来阅读
void proc_arr(int (*array)[10][10])
那么你的代码应该像书面一样工作。
下表显示了给定特定声明的各种数组表达式的类型。
声明:T a [M]; 表达类型衰变为 ---------- ---- --------- a T [M] T * &a T(*)[M] *在 a [i] T 声明:T a [M] [N]; 表达类型衰变为 ---------- ---- --------- a T [M] [N] T(*)[N] &a T(*)[M] [N] * a T [N] T * a [i] T [N] T * &a [i] T(*)[N] * a [i] T a [i] [j] T 声明:T a [M] [N] [O]; 表达类型衰变为 ---------- ---- --------- a T [M] [N] [O] T(*)[N] [O] &a T(*)[M] [N] [O] * a T [N] [O] T(*)[O] a [i] T [N] [O] T(*)[O] &a [i] T(*)[N] [O] * a [i] T [N] T * a [i] [j] T [N] T * &a [i] [j] T(*)[N] * a [i] [j] T a [i] [j] [k] T
高维数组的模式应该清晰。
这不起作用:
void proc_arr(int ***array) { (*array)[0][1] = 10; }
因为,在幕后,编译器必须将其更改为相对于数组开头的内存偏移量。 这意味着它需要知道数组的尺寸。 您尚未在函数签名中声明这些内容。