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

ber*_*zie 4 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;
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我想进入array内部时proc_arr,我不能.根据我的理解,我们应该这样访问它:

void proc_arr(int ***array)
{
    (*array)[0][1] = 10;
}
Run Code Online (Sandbox Code Playgroud)

因此,我决定array告诉编译器我想转到该地址并获取值.但不知何故,它崩溃了.我已经尝试了几种组合*和括号,仍然无法使其工作.我很确定这是因为我不理解指针和指针指针.

哦,我注意到如果我们使用char **(字符串数组)也是不同的,就像argv和envp一样.但是对于envp,我可以以某种方式访问​​它(*envp).为什么?

这是促使envp(和工作)的函数:

int envplen(char ***envp)
{
    int count = 0;

    while((*envp)[count] != NULL)
    {
        count++;
    }

    return count;
}
Run Code Online (Sandbox Code Playgroud)

此外,我可以以某种方式只envpenvplen函数中访问envp,但仍然通过引用传递它?

谢谢你.

Jas*_*son 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 |
Run Code Online (Sandbox Code Playgroud)

所以当你隐式地将数组转换为a 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|
Run Code Online (Sandbox Code Playgroud)