此代码:
#include <stdio.h>
int main() {
int num;
int *pi;
num = 0;
pi = #
printf("address: %p | %d\nvalue: %d\n", pi, pi, *pi);
}
生成此输出:
address: 0x7fff5952f9cc | 1498610124
value: 0
我知道左边的那个应该是正确的地址,但是地址旁边打印的是什么?
答案 0 :(得分:5)
%p
告诉printf
将相应的变量视为指针,因此printf
将p
打印为指针;也就是说,十六进制表示(即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函数):
如果任何参数不是相应转换规范的正确类型,则行为未定义。
您使用两个格式说明符pi
和int
打印%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
。