多维数组的指针如何在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; } 

另外,我可以以envpenvplen函数中以某种方式访问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; } 

因为,在幕后,编译器必须将其更改为相对于数组开头的内存偏移量。 这意味着它需要知道数组的尺寸。 您尚未在函数签名中声明这些内容。