打印2D数组`arr`时`*((* arr +(i * 3))+ j)`如何工作?

时间:2015-06-02 12:16:34

标签: c arrays pointers multidimensional-array

代码:

#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]

这如何打印最后三个值?

3 个答案:

答案 0 :(得分:3)

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

第二行:     i = 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]

答案 1 :(得分:3)

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;时一样。
  • 初始化列表中的初始值设定项将按照列出的顺序复制到内存位置。

答案 2 :(得分:0)

数组存储在您的存储器中,如:

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

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

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