C语言指针操作疑问:打印ptr为何输出数值而非地址?
指针越界操作导致输出异常的问题解析
问题回顾
你尝试运行了一段指针相关的代码,却遇到了和预期不符的输出:
原代码(注释掉第一个printf):
#include <stdio.h> int main(){ int x = 3; int *ptr = &x; //printf("Address is : %d\n",&ptr); ptr++; *ptr = 1; printf("%d %d",x,ptr); return 0; }
输出是 3 1,但你预期应该是3加上ptr的地址;取消注释第一个printf后,输出变成Address is : 6356744 3 6356752,这让你困惑不解。
问题根源:未定义行为(Undefined Behavior)
咱们一步步拆解这个问题的核心:
1. 指针越界的非法写入
你初始化ptr指向变量x的地址,执行ptr++后,ptr会移动到x之后的未被你声明的变量占用的栈内存区域(因为int类型通常占4字节,所以ptr会往后跳4个字节)。
这时候你执行*ptr = 1;,本质是在写入不属于你的内存空间——这种操作属于C语言里的未定义行为,意味着编译器和运行时可以做任何事情:可能覆盖其他变量、可能让程序崩溃,也可能出现你看到的奇怪输出,完全没有规律可言。
2. 第一次输出3 1的原因
当你注释掉第一个printf时,栈的布局比较紧凑:ptr++后的地址刚好指向了ptr自身在栈上的存储位置。你执行*ptr =1,相当于把ptr变量本身的值改成了1,之后用%d打印ptr时,自然就输出了1(另外,用%d打印指针本身也是不规范的,正确应该用%p)。
3. 取消注释后输出正常的原因
当你加上第一个printf调用后,栈的布局被改变了:函数调用会在栈上压入一些临时数据(比如返回地址、参数等),导致ptr++后的地址不再指向ptr自身的存储位置。这时候*ptr =1写入的是一块无关的栈空间,不会影响ptr的值,所以你打印ptr时,它就是自增后的正常地址(6356752),x的值也没被改动,最终输出符合你的预期。
几个关键的注意事项
- 绝对不要访问或写入指针越界的内存,未定义行为的结果完全不可预测,调试起来也非常麻烦。
- 打印指针地址时,必须使用
%p格式符,并且要把指针强制转换为void*,比如:printf("ptr的地址是:%p\n", (void*)ptr);。 - 栈内存的布局会随着函数内的变量声明、函数调用而动态变化,这也是为什么两次运行结果截然不同的核心原因。
内容的提问来源于stack exchange,提问作者SwiftDeath
相关产品推荐
相关产品推荐

