1

为什么此代码打印 4 作为输出?

还请提供一些详细信息,以帮助我更好地理解这种行为。

int main(){ 
     int *p=NULL;
     printf("%d" ,p+1);
     return 0; 
}
4

5 回答 5

9

您将指针设置为 0 (NULL),然后向其添加 1;然后您将结果转换为int并打印结果。您在这里需要的关键知识是,当您递增(加 1 到)一个指针时,实际上是添加了指向对象的大小——一个int指针前进到指向下一个 int。因为intis (显然)在您的平台上p是 4 个字节,所以会递增以指向一个地址,该地址比它开始的位置 4 个字节。

于 2012-06-10T15:11:39.653 回答
3

值得注意的是,这p + 1是一个无效的指针(即,一个既不是NULL也不是指向有效对象/超过数组对象的指针),任何使用它都是未定义的行为。

printf("%d" ,p+1);

或(更正确):

printf("%p", (void *) (p + 1));

是未定义的行为。

于 2012-06-10T15:16:06.373 回答
3

C 中的大小int(通常)为 4 个字节。因此,将指针增加一个单位意味着将其值增加sizeof(int).

此外,您不是打印指针指向的值(因为这肯定会使您的程序崩溃),而是指针本身的值。您绝对应该看一下 C(或一般)中的任何指针教程。

于 2012-06-10T15:13:26.300 回答
1

你得到未定义的行为。仅当指针指向数组的元素或数组末尾之外的元素并且将指针移动整数表示的位置数的结果也指向的元素时,才向指针添加整数有效相同的数组,或者一个超出末尾的数组。(出于这些目的,非数组对象可以被视为单元素数组的唯一元素。)

空指针不指向数组的元素,因此您不能向其添加一个元素。(在 C++ 中,明确允许将 0 添加到空指针值并获得空指针值作为结果。(请参阅Andrew Koenig 在 Dobb 博士的这篇博客条目。)

通过将指针值传递给相应的格式说明符所期望的位置,您可以获得更多未定义的行为。是 的正确格式说明符,如果要将指针打印为with ,则需要显式转换。printf%dint%pvoid*int%d

如果您的程序具有未定义的行为,则无法保证可能发生的任何事情。你当然不能通过观察结果来推断出任何关于语言的东西,并且有争议的是,试图从这样的行为中推断出实现的属性有什么优点,因为没有进一步的证据,即从程序中观察到的结果的形式没有如果编译器供应商有未定义的行为或保证,您将不知道哪些情况可能会导致观察到的行为发生变化。

于 2012-06-10T15:17:42.807 回答
1

您正在打印 p 的地址,而不是存储在地址 p 的值。p = NULL 将 p 设置为零。由于它是一个指向整数的指针,因此将其递增 1 实际上会使指针递增整数的大小,通常为 4 或 8 个字节。

尝试通过 *p 打印存储在地址 0(甚至 4)的内容通常会在大多数系统上终止您的程序,因为该内存区域受到保护。

于 2012-06-10T15:13:46.817 回答