多维数组的指针如何在C中工作

时间:2011-08-23 12:48:37

标签: c pointers multidimensional-array

我在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,但仍然可以通过引用传递它吗?

先谢谢。

3 个答案:

答案 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;
}

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