代码:
#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]
。
这如何打印最后三个值?
答案 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]
:x
为arr[1]
,n
为0
,因此首先等同于:*(arr[1] + 0)
第二个x
为arr
,n
为1
,因此*(*(arr + 1) + 0)
。
最后arr + 1
表示arr + sizeof(*arr)
处的地址,表示:
(arr + 1)
相当于(*arr + 3)
,因为*arr
为arr[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