&地址与指针地址的差异:十六进制与指针类型数据解析
指针地址输出:%x与%p的差异解析
核心问题:格式符用途与地址位数不匹配
你看到的输出差异,本质是错误使用格式符导致的地址截断,具体细节如下:
- %x的本质:
%x是C标准中用于输出32位无符号整数的十六进制格式符。当你用它打印64位系统下的指针(指针为8字节/64位)时,会仅保留地址的低32位,直接丢弃高位字节。你看到的a6bff9c4就是完整地址的低32位部分。 - %p的本质:
%p是C标准专门为指针设计的格式符,会根据当前系统的指针位数(32位/64位)完整输出指针的全部字节。在64位系统下,它会输出完整的64位十六进制地址,也就是你看到的000000f5a6bff9c4——其中000000f5就是被%x截断的高位部分。
为什么会出现"前加000000f5"的现象
在64位Windows环境中,用户态进程的虚拟地址通常低48位有效,部分场景下会有高位扩展(比如你的例子里的000000f5)。但无论高位值是什么,%x都会只截取低32位输出,%p则会输出完整的指针值,所以看起来像是%p的结果在%x的结果前补充了高位字节。
重要规范:禁止用%x打印指针
用%x打印指针属于未定义行为——%x期望接收unsigned int类型参数,但64位系统下指针是unsigned long long类型,类型不匹配会导致不可预期的输出。打印指针地址的正确做法永远是使用%p。
验证代码
如果想直观确认完整地址,可使用%llx(输出64位无符号整数的十六进制)打印强制转换后的指针,结果会和%p完全一致:
#include <stdio.h> int main() { int a=8; int *ptr=&a; printf("\n&a (%%x): %x\n",&a); printf("\nptr (%%p): %p \n",ptr); printf("\n&a (完整64位地址 %%llx): %llx\n", (unsigned long long)&a); return 0; }
内容的提问来源于stack exchange,提问作者NeuronB
相关产品推荐
相关产品推荐

