可能重复:
二维数组如何在内存中格式化?
int map[3][3] = {1,2,3,4,5,6,7,8,9};
int **p = map;
printf( "%d", *p+1 );
有人能告诉我为什么结果是5吗?而如果
printf( "%d", *p+2);
结果是9?(由 Visual C++ 编译)
可能重复:
二维数组如何在内存中格式化?
int map[3][3] = {1,2,3,4,5,6,7,8,9};
int **p = map;
printf( "%d", *p+1 );
有人能告诉我为什么结果是5吗?而如果
printf( "%d", *p+2);
结果是9?(由 Visual C++ 编译)
因为数组不是指针。双指针不等同于二维数组,因为数组在内存中是连续的。您的数组已创建并填充数据,如下所示:
map[0][0] = 1
map[0][1] = 2
map[0][2] = 3
map[1][0] = 4
map[1][1] = 5
map[1][2] = 6
map[2][0] = 7
map[2][1] = 8
map[2][2] = 9
当您将其分配给双指针时,您做错了几件事。例如:
printf("%d", *p + 1);
不做你认为它做的事。这是未定义的行为,因为*p
is的类型int *
但%d
格式说明符需要int
. 基本上,不要试图将数组视为指针,因为它们不一样。请阅读C FAQ 的相关部分,以了解如何正确处理这种情况。基本上,在这种情况下使用一维指针并正确索引就足够了。
示范:
要修改 H2C03 的答案...
您的第一个 deref 会将您带入数组 1 维度。具体来说,它让您指向“1”的条目。
这里的大多数人似乎并没有完全弄清楚接下来会发生什么。此时' p'仍然被认为是一个指针。它认为它包含地址“1”。当您执行“+1”时,您实际上得到的是指针算术。由于 sizeof(int ) (通常)为 4,因此您只需打印矩阵 +4 的第一个元素。因此 +2 转换为 +8 因为指针运算总是根据指针指向的“事物”的大小来完成。所以你得到 5 和 9。
将显示代码的快速解除。
mov eax, DWORD PTR ?p@@3PAPAHA ; p
mov ecx, DWORD PTR [eax] ; deref of p (which is '1')
add ecx, 4 ; let's just +4 it and push it as the arg to printf
push ecx
push OFFSET $SG3670
call _printf