指针入门疑问:%i值一致但%p值不同的原因解析
指针与int变量的printf输出问题解析
先看你的代码:
int main(void) { int n = 50; int *p = &n; int t = &n; // using %p below printf("%p\n", p); printf("%p\n", &n); printf("%p\n", t); // using %i below printf("%i\n", p); printf("%i\n", &n); printf("%i\n", t); }
示例输出:
0x7ffc3f503cd8 0x7ffc3f503cd8 0x3f503cd8 1062223064 1062223064 1062223064
核心问题根源
代码里int t = &n;是关键:你把8字节的内存地址(指针类型)直接赋值给了4字节的int变量t,地址的高4字节被截断丢失,只保留低4字节存在t中。
一、为什么%i输出完全一致?
%i是打印十进制整数的格式符:
- 打印
p或&n时,printf会把8字节的指针值强制转换成int类型(只取低4字节),输出这部分的十进制数值。 - 打印
t时,t本身存的就是地址的低4字节,直接输出它的十进制值即可。
三者的%i输出本质都是原地址低4字节的十进制表示,所以完全相同。
二、为什么%p输出t和另外两个不同?
%p是专门打印内存地址的格式符,要求传入void*类型(8字节):
- 打印
p或&n时,int*类型的指针会自动转为void*,printf输出完整的8字节地址,也就是0x7ffc3f503cd8。 - 打印
t时,t是4字节的int变量,传给printf后会被当成void*处理,但它只有4字节的有效数据(原地址的低4字节),高4字节补0,所以输出的是0x3f503cd8——也就是被截断后的地址片段,自然和完整地址不同。
重要提醒
这种将指针直接赋值给int变量的行为属于C语言未定义行为,不同系统、编译器下可能出现不同结果,实际开发中绝对不能这么写。
内容的提问来源于stack exchange,提问作者Abedbeginnings
相关产品推荐
相关产品推荐

