【问题标题】:How does `*((*arr+(i*3))+j)` work when printing a 2D array `arr`?打印二维数组 `arr` 时,`*(((*arr+(i*3))+j)` 是如何工作的?
【发布时间】:2015-08-16 05:33:22
【问题描述】:

代码:

#include <stdio.h>

int main(void)
{
    int arr[2][3] = {{1,2,3},{4,5,6}};
    int i, j;

    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 3; j++)
        {
            printf("%d ", *((*arr+(i*3))+j));
        }
        printf("\n");
    }

    return 0;
}

我很惊讶上面的代码如何给出输出:

1 2 3   
4 5 6

我知道*(arr+i) == arr[i] 并且我应该使用arr[i][j] 而不是让一切变得更复杂,但我不明白*((*arr+(i*3))+j) 是如何工作的。

据我了解,*((*arr+(i*3))+j) 可以简化为 *((*arr)+(i*3)+j),因为 *(间接运算符)在这里具有最高优先级。

因此,当i 为零并且j 迭代从0 到2 时,表达式与打印第一个子数组的整数的arr[0][j] 相同。

i 变为 1 时,我的困惑就增加了。接下来的三个表达式将是 *((*arr)+(1*3)+0)*((*arr)+(1*3)+1)*((*arr)+(1*3)+2),可以简化为 arr[0][3]arr[0][4]arr[0][5]

这如何打印最后三个值?

【问题讨论】:

  • 数组值是连续存储的。
  • 这是否意味着arr[0][3] == arr[1][0]arr[0][4] == arr[1][1]arr[0][5] == arr[1][2]

标签: c arrays pointers multidimensional-array


【解决方案1】:
int arr[2][3] = {{1,2,3},{4,5,6}};

在内存中:

1 | 2 | 3 | 4 | 5 | 6
each number on an adjacent memory "cell" the size of an int, in this order

第二行: 我 = 1 j = 0

*((*arr+(i*3))+j)) means *((*arr + 3) + 0)-> *({1, 2, 3} + 3) -> *({4, 5, 6}) = 4

请记住,x[n] 等同于 *(x + n),无论是 x 还是 n。 (这也意味着arr[1] 等价于*(arr + 1)*(1 + arr)1[arr],我觉得这很有趣)

这里 arr[1][0]xarr[1]n0 所以第一个等价:*(arr[1] + 0)
第二个xarrn1 所以*(*(arr + 1) + 0)
最后arr + 1 表示arr + sizeof(*arr) 的地址,这意味着: (arr + 1) 等价于 (*arr + 3),因为 *arrarr[0] 类型为 int[3]

【讨论】:

  • 不错的答案。不过,我仍然感到困惑(“arr + 1 表示 arr 加上一个 arr 的大小,相当于 *((*arr + 3) + 0))”)。我想我需要打个盹才能理解。感谢您的回答!
  • 是的,抱歉,有点不清楚。例如,如果您有一个char *s,当您执行s = s + 1 时,指针将向前推进一个char。如果你有int *p 并且你有p = p + 1 指针向前推进一个int,这是不一样的^^
【解决方案2】:

C 语言以所谓的行优先顺序存储多维数组, 因此,当您声明 int arr[2][3] 时,内存实际上是由数组的条目在 按此顺序记忆:

arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]

这有几个有用的结果:

  • arr[1] 就像一个指向一维数组的指针。就像声明 int **arr; 时一样。
  • 初始化列表中的初始化程序会按照您列出它们的顺序复制到内存位置。

【讨论】:

    【解决方案3】:

    数组存储在您的内存中,如下所示:

    _____ _____  _____  _____  _____  _____  
    | 1 | | 2 |  | 3 |  | 4 |  | 5 |  | 6 |
    ----- -----  -----  -----  -----  -----
    

    因此,即使它存储在二维数组中,它也会在编译期间传染性地分配内存。当您编写 a[1][1] 时,编译器从前面访问 (1*(no of columns) + 1 ) 位置,即从开始的 4 位置。

    http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html

    【讨论】:

      猜你喜欢
      • 2017-12-09
      • 2023-01-11
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      相关资源
      最近更新 更多