请解释第一个和最后一个printf
语句的输出。我认为他们应该提供相同的输出。
int main()
{
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
printf("%d\n", (&arr + 1) - &arr);
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
return 0;
}
输出:
1
210
42
210
答案 0 :(得分:4)
让我们先看看内存布局:
char arr[5][7][6];
此处arr
是一组数组数组。
它将被安排到内存中,如下所示:
+--------------+
| | arr[0]
+--------------+
| | arr[1]
+--------------+
| | arr[2]
+--------------+
| | arr[3]
+--------------+
etc.
现在arr[i]
是char
的数组数组。
所以a[i]
就像
+--------------+ a[i][0]
| |
+--------------+
| | a[i][1]
+--------------+
| | a[i][2]
+--------------+
| | a[i][3]
+--------------+
etc
现在arr[i][j]
是chars
的数组。
所以
+--------------+
| | arr[i][j][0]
+--------------+
| | arr[i][j][1]
+--------------+
| | arr[i][j][2]
+--------------+
etc.
编译器将在其符号表中创建一个名为arr
的条目,并使用其第一个块的地址,并跟踪总大小(5 * 6 * 7 = 210个字节)。
现在是表达式
printf("%d\n", (&arr + 1) - &arr);
它是一个指针算术。所以它必然会键入每个符号。
让我们看看这一点。
(gdb) p &arr
$1 = (char (*)[5][7][6]) 0x7fffffffe160
您会看到arr
的类型是指针char (*)[5][6][7]
换句话说,它指向数组数组的指针。指针算术实际上与指针所指向的类型有关。所以重要的是这种类型的大小。
(gdb) p sizeof(char [5][7][6])
$2 = 210
因此任何指向类型char [5][6][7]
的指针都将递增或递减,如下所示:
&arr+1 => 0x7fffffffe160 +0xd2 => 0x7fffffffe232
和(&arr + 1) - &arr => 0x7fffffffe232 - 0x7fffffffe160=> 0xd2
现在它实际返回 0xd2 。但对于指针算术,它意味着1*sizeof(char [5][7][6]) => 1
指针算术返回number of sizeof(type)
而不是实际的字节偏移量。
您的
结果正确无误printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
因为你正在使它成为一个char指针。因此指针算术将使用1字节大小的单位sizeof(char)
。因此输出将是210。
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
表达式中的arr
将衰减为char (*)[7][6]
,因此它是指向二维数组的指针。它指向的类型大小为6 * 7 = 42.这就是你得到的结果。
printf(“%d \ n”,(无符号)(p + 1) - (无符号)p);
此处,p+1 - p
将导致指针算术1 * sizeof(char(*)[5][6][7])
。所以在指针运算中,它应该返回1.但是由于你将结果转换为无符号,它将放弃指针运算并使用整数运算。由于使用整数运算,它将处理大数字的指针值,因此您将获得实际的字节偏移量。
答案 1 :(得分:2)
如果它们被视为指针,它们将打印相同的结果,但在最后printf
中,您强制它们通过强制转换被视为无符号整数。因此,在整数算术规则之后减去p + 1
和p
,而不是指针算术规则。
让事情变得更加清晰:
unsigned
时,您告诉编译器
“这些只是简单的数字,没有什么可看的”。所以编译器对待
地址为数字,只是减去它们。答案 2 :(得分:0)
第一个获取arr
的地址并添加一个,然后减去地址,结果显然为1.
最后一个,p
是指向char [5][7][7]
的指针,使用(*p)[x][y][z]
可以是p[0][x][y][z]
。因此,(p + 1)
可以被视为p[1]
,距离5 * 7 * 6
为210(p
}个字节。
如果你(((unsigned) p) + 1) - ((unsigned) p)
那么那就是1
。
答案 3 :(得分:0)
地址之间的距离是1个元素或210个字节
第一张打印件打印元素数量 最后一个 - 字节数