【问题标题】:Questions about multi dementional array decaying and accessing them关于多维数组衰减和访问它们的问题
【发布时间】:2021-05-15 15:36:21
【问题描述】:

我了解一维数组指针的工作原理,但我不明白二维数组指针的工作原理。

我知道array1[0] == *(array1 + 0),但我不知道如何在二维数组中使用这种形式。 我发现如果我使用双指针或'[]'(我不知道这是什么),那么它可以工作。

  1. 如何使用指针访问多维数组?

  2. 可以使用双指针或'[]'吗?如果是,为什么?

  3. 为什么 *(2Darrayname + number) 不起作用?

  4. 是不是因为腐烂了? (我不知道腐烂的东西)

编辑)我已经检查了这些 What is array to pointer decay? Pointers in C: when to use the ampersand and the asterisk? Accessing multi-dimensional arrays in C using pointer notation

int main()
{
    int array1[5];
    int array2[5][5];

    f1(array1);
    f2(array2);
}

int f1(int *p1)
{
    for(int i = 0; i<5 ; i++)
    {
        printf("%d", *(p1+i));    //this is ok
    }
}

int f2(int (*p2)[5])
{
    for(int i = 0; i<5 ; i++)
    {
        printf("%d", *(p2+i));    //this one makes error, and gcc says it is 'int *'
        printf("%d", *(p2+i)[1]); //and this one is ok for some reason
        printf("%d", **(p2+i));   //this one too. why is this ok??
    }
}

【问题讨论】:

    标签: arrays c pointers


    【解决方案1】:

    您对“2D 数组”在 C 中不明确这一事实感到困惑——有两种完全不同的东西可以称为“2D 数组”,这源于数组本身是 1D 的事实,但是可以由其他东西(包括数组)组成,它们会衰减为指针。

    所以当有人说“二维数组”时,他们可能在谈论:

    • 数组数组
    • 一个指针数组(指向数组)

    这两件事非常不同(有不同的、不兼容的类型),需要以不同的方式创建。但是,访问这两个东西的语法是完全相同的(/ 可用于除整数或浮点值的方式非常相似,但“幕后”的行为却截然不同。 )

    访问语法相同的原因是由于指针衰减——当您有一个数组数组时,解引用会为您提供一个立即衰减为指针的数组。当你有一个指针数组时,解引用它会直接给你一个指针。


    在您的示例中,您有一个数组数组,它​​立即衰减为指向 5 个整数数组的指针。这显示为 f2 的参数:

    int f2(int (*p2)[5])
    

    这里的 p2 是一个指向 5 个整数数组的指针——它可能是单个数组,也可能是数组数组的第一个元素,这就是你实际调用它的方式。

    printf("%d", *(p2+i));
    

    p2 是指向数组的指针,p2+i 为您提供指向第 i 个 5 个整数数组的指针。然后,您取消引用它以获得 5 个 int 的数组,该数组立即衰减为指向数组中第一个 int 的指针(和int *)。由于这与 printf 格式(需要一个 int)不匹配,因此您会得到未定义的行为。

    printf("%d", *(p2+i)[1]);
    

    这里第一步是一样的,给第i个数组的指针。然后,您对其执行 [1] 索引(请记住,后缀操作的优先级始终高于前缀),它会获取数组数组的第 (i + 1) 个元素。由于这是一个数组(5 个整数),它立即衰减为一个指针,然后取消引用,为您提供与 printf 格式匹配的 int。这个表达式等价于p2[i+1][0],这样更容易理解。

    printf("%d", **(p2+i));
    

    这里,这相当于第一种情况,上面多了一个*。所以导致第一种情况的int * 被取消引用到int。等同于p2[i][0]

    【讨论】:

      【解决方案2】:

      假设数组名是arr

      1. 访问二维数组的元素:arr[i][j]
      2. 使用 arr[i] 只是表示 *(arr + i) 的另一种方式。
      3. 如果它是一个二维数组,那么您必须取消引用两次才能访问一个元素。 *(arr + num) 只会将您带到数组第 num 行的基地址,因此它不起作用。因此,所有这些都是等价的形式。

      arr[i][j]*(*(arr + i) + j)*(arr[i] + j)

      所以arr是一个二维数组指针,也就是说它存储了arr[0]的地址,arr[0]存储了arr[0][0]的地址,所以arr可以理解为指向指针的指针。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-06
        • 1970-01-01
        • 1970-01-01
        • 2020-05-18
        • 2011-02-09
        • 1970-01-01
        • 2015-08-10
        相关资源
        最近更新 更多