我在C中尝试指向多维数组的概念。假设我想通过函数处理多维数组。代码有点像这样:
#include <stdio.h>
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;
}
问题是,当我想在array
内访问proc_arr
时,我不能。根据我的理解,我们应该这样访问它:
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
,但仍然可以通过引用传递它吗?
先谢谢。
答案 0 :(得分:8)
问题是因为在堆栈上分配的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|
答案 1 :(得分:4)
您的类型不匹配。鉴于声明int array[10][10]
,表达式&array
的类型将为int (*)[10][10]
,不 int ***
。如果您将函数原型更改为
void proc_arr(int (*array)[10][10])
然后你的代码应该按照书面形式工作。
下表显示了给定特定声明的各种数组表达式的类型。
Declaration: T a[M]; Expression Type Decays To ---------- ---- --------- a T [M] T * &a T (*)[M] *a T a[i] T Declaration: T a[M][N]; Expression Type Decays To ---------- ---- --------- 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 Declaration: T a[M][N][O]; Expression Type Decays To ---------- ---- --------- 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
高维数组的模式应该清晰。
答案 2 :(得分:2)
这不起作用:
void proc_arr(int ***array)
{
(*array)[0][1] = 10;
}
因为在幕后,编译器必须将其更改为相对于数组开头的内存偏移量。这意味着它需要知道数组的尺寸。您尚未在函数签名中声明这些内容。