You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:36:08