用%d打印int指针时打印出来的是什么?

时间:2015-03-19 05:25:56

标签: c pointers

此代码:

#include <stdio.h>

int main() {
    int num;
    int *pi;
    num = 0;
    pi = &num;
    printf("address: %p | %d\nvalue: %d\n", pi, pi, *pi);
}

生成此输出:

address: 0x7fff5952f9cc | 1498610124
value: 0

我知道左边的那个应该是正确的地址,但是地址旁边打印的是什么?

8 个答案:

答案 0 :(得分:5)

%p告诉printf将相应的变量视为指针,因此printfp打印为指针;也就是说,十六进制表示(即0x7fff5952f9cc)。另一方面,%d告诉printf将相应的变量视为数字。因此,正在打印的是p实际,数字值(即1498610124),它在基数10中仅为0x5952f9cc。

现在,同一个变量的这两个表示似乎具有不同值的原因是%d只告诉printf期望一个数字---它没有指定该数字的类型。如果将0x7fff5952f9cc(64位整数)转换为int(32位类型),则会得到1498610124(注意0x7fff被删除)。

答案 1 :(得分:3)

您打印的地址是十进制而不是十六进制,但会被截断为int

答案 2 :(得分:2)

我猜你正在64bit机器上执行这个程序。

地址旁边打印的数字仍然是以整数格式打印的指针的地址。 您还可以看到该值被截断

0x7fff5952f9cc = 140734691998156的十进制数。但它被打印为1498610124,这是由于截断。

答案 3 :(得分:1)

您正尝试分别以十六进制和十进制值打印num的地址。如果我没有错,那么你在64位架构上运行你的程序,因此地址将是8个字节。所以你的地址适合长数据类型。通过给%d,你的价值在这里被截断了。而不是%d请使用%ld。所以你的printf语句应该实际如下

printf(“地址:%p |%ld \ nvalue:%d \ n”,pi,pi,* pi);

现在运行程序,您将以十进制格式正确获取您的值。

答案 4 :(得分:1)

它可以是任何东西,因为它是未定义的行为。 (C标准,§7.21.6.1, fprintf函数):

  

如果任何参数不是相应转换规范的正确类型,则行为未定义。

您使用两个格式说明符piint打印%p(指向%d的指针)。根据C标准(并且可能在您的系统上man fprintf逐字逐句复制):

  • d,i int参数将转换为样式 [ - ] dddd
  • 中的带符号小数
  • p参数应为指向void的指针。指针的值以实现定义的方式转换为打印字符序列。

所以这些用途都不正确。它不是void的指针,也不是int。所以你应该写的是:

printf("address: %p | %d\nvalue: %d\n", (void*)pi, (int)pi, *pi);

在您的系统上,这可能会产生相同的输出(未定义的行为包括意外产生错误预期的行为)但它可能不会。在任何情况下,正确地写行都会使得打印的第二个数字相对清楚:它是指针转换为整数的值。

然而,无法保证这也会起作用。再次,从标准(§6.3.2.3,指针,第6段):

  

任何指针类型都可以转换为整数类型。除了之前指定的以外,结果是实现定义的。如果结果无法以整数类型表示,则行为未定义。

(“先前指定的”情况是NULL指针可以可靠地转换为任何整数类型;它将具有值0。)

所以我的想法是指针很像整数,但它可能是long的大小。或long long。或者是其他东西。它甚至可能比任何整数类型都大,但是如果有一些大小合适的整数类型而且你是#include <stdint.h>,那么整数类型将被{type = 1}}和它的无符号版本(可能是更有用)将是intptr_t。不幸的是,这些尺寸没有标准的uintptr_t转换,所以如果你真的想要,你需要printf并写下:

#include <intypes.h>

或者,因为总是允许将任何整数转换为任何 unsigned 整数(可能丢失信息,但转换定义明确),您可以使用两个强制转换:

printf("address: %p | %" PRIuPTR "\nvalue: %d\n",
       (void*)pi, (uintptr_t)pi, *pi);

(因为它提供printf("address: %p | %u\nvalue: %d\n", (void*)pi, (unsigned)(uintptr_t)pi, *pi); 参数,格式说明符必须为unsigned int而不是u。)

答案 5 :(得分:0)

使用printf时,“p”修饰符用于以十六进制格式打印出内存地址。 “d”修饰符告诉它将值转换为有符号整数值。因此它需要使用0x7fff5952f9cc并将其转换为带符号的int。

有关printf的更多详细信息,请参阅this

答案 6 :(得分:0)

在该代码中,必须将地址打印为%d,因此在编译期间显示警告,%p显示十六进制,但%d显示整数。

答案 7 :(得分:0)

指针值的下半部分 - 4个最低有效字节 - 十进制:
0x5952F9CC == 1498610124