为什么此代码打印4作为输出?
请提供一些细节,以帮助我更好地理解这种行为。
int main(){
int *p=NULL;
printf("%d" ,p+1);
return 0;
}
答案 0 :(得分:9)
您将指针设置为0(NULL),然后向其添加1;然后你将结果转换为int
并打印结果。这里需要的关键知识是当你递增(加1)一个指针时,你实际上添加了指向对象的大小 - 一个int
指针被提前指向下一步 int
。由于int
(显然)是您平台上的4个字节,因此p
会增加到指向其开始的4个字节的地址。
答案 1 :(得分:3)
C中int
的大小(通常)为4个字节。因此,将指针递增一个单位意味着将其值增加sizeof(int)
。
此外,您不打印指向哪个指针的值(因为这肯定会使程序崩溃),而是指针本身的值。你一定要看看C中的任何指针教程(或者一般)。
答案 2 :(得分:3)
值得注意的是p + 1
是一个无效指针(即指针既不是NULL
也不是指向有效对象/一个超过数组对象的指针)并且它的任何使用都是未定义的行为。
printf("%d" ,p+1);
或(更正确):
printf("%p", (void *) (p + 1));
是未定义的行为。
答案 3 :(得分:1)
您正在打印p的地址,而不是AT地址p的存储值。 p = NULL将p设置为零。因为它是一个指向整数的指针,所以将它递增1实际上会使指针增加一个整数的大小,通常为4或8个字节。
尝试通过* p打印存储在地址零(或甚至4)的内容通常会在大多数系统上终止程序,因为该内存区域受到保护。
答案 4 :(得分:1)
您正在获取未定义的行为。只有当指针指向数组的元素或超出数组末尾的指针时才向指针添加整数才有效,并且通过整数表示的位置数移动指针的结果也指向元素相同的数组,或超越结束的数组。 (出于这些目的,非数组对象可以被视为一个元素数组的唯一元素。)
空指针不指向数组的元素,因此您无法向其中添加一个元素。 (在C ++中,显式允许将0添加到空指针值并获得空指针值。(请参阅Dobb博士的Andrew Koenig的this blog entry。)
您可以通过将指针值传递给printf
来获得进一步的未定义行为,其中相应的格式说明符为%d
,期望为int
。 %p
是void*
的正确格式说明符,如果要将指针打印为int
%d
,则需要显式转换。
如果您的程序有未定义的行为,则无法保证可能发生的任何事情。你当然无法从观察结果中推断出有关语言的任何内容,并且可以说有什么优点是试图从这种行为推断实现的属性,没有进一步的证据形式的可观察结果的程序不拥有未定义的行为或来自编译器供应商的保证,您将不知道什么情况可能导致观察到的行为发生变化。