【问题标题】:How Pointer of Multi-Dimension Arrays Work in C多维数组的指针如何在 C 中工作
【发布时间】:2011-11-01 22:32:48
【问题描述】:

我正在尝试使用 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;
}

问题是,当我想在proc_arr 中访问array 时,我不能。据我了解,我们应该以这种方式访问​​它:

void proc_arr(int ***array)
{
    (*array)[0][1] = 10;
}

所以我取消引用array 来告诉编译器我想去那个地址并获取值。但不知何故,它崩溃了。我尝试了* 和括号的几种组合,但仍然无法正常工作。我很确定是因为我不了解指针和指针的指针。

哦,我注意到如果我们也使用 char **(字符串数组) 会有所不同,例如 argv 和 envp。但是对于 envp,我可以通过 (*envp) 访问它。为什么?

这是 procces envp(并有效)的函数:

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

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

    return count;
}

另外,我是否可以在 envplen 函数中仅使用 envp 访问 envp,但仍然通过引用传递它?

之前谢谢。

【问题讨论】:

    标签: c pointers multidimensional-array


    【解决方案1】:

    问题是因为分配在堆栈上的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|
    

    【讨论】:

    • 好的,我想我明白了:数组不是指针。谢谢。
    【解决方案2】:

    您的类型不匹配。给定声明 int array[10][10],表达式 &amp;array 的类型将是 int (*)[10][10]not int ***。如果您将函数原型更改为读取

    void proc_arr(int (*array)[10][10])
    

    那么您的代码应该可以正常工作。

    下表显示了给定特定声明的各种数组表达式的类型。

    声明:Ta[M]; 表达式类型衰减到 ---------- ---- --------- 一个 T [M] T * &a T (*)[M] *在 一个[我] T 声明:Ta[M][N]; 表达式类型衰减到 ---------- ---- --------- 一个 T [M][N] T (*)[N] &a T(*)[M][N] *一个 T [N] T * a[i] T [N] T * &a[i] T (*)[N] *a[i] T a[i][j]T 声明:T a[M][N][O]; 表达式类型衰减到 ---------- ---- --------- 一个 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]

    高维数组的模式应该是清晰的。

    【讨论】:

      【解决方案3】:

      这行不通:

      void proc_arr(int ***array)
      {
          (*array)[0][1] = 10;
      }
      

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

      【讨论】:

        猜你喜欢
        • 2021-07-06
        • 1970-01-01
        • 1970-01-01
        • 2021-12-02
        • 1970-01-01
        • 1970-01-01
        • 2013-04-29
        • 2012-06-10
        相关资源
        最近更新 更多