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

为何printf中取地址运算符会使函数指针输出变为0x1000?

问题原因与含义解析

核心前提:未初始化的函数指针变量

你定义的int (*fp)(int)是一个自动存储期的函数指针变量(默认在栈上分配内存),但未对其进行初始化。根据C语言标准,这类未初始化的自动变量的值属于不确定值,直接使用该变量属于未定义行为——编译器可自由处理这种情况,没有固定的预期结果。

两种场景的具体解释

场景1:两次调用printf("%p", fp)输出一致

这种“一致输出”只是巧合,并非必然结果。未初始化变量的不确定值通常来自栈上的残留数据,连续两次读取时,栈上的这部分数据尚未被修改,因此凑巧读到相同的值。但该结果完全依赖于编译器实现与运行环境,更换环境或编译器后,输出可能完全不同。

场景2:第一次printf("%p", fp)输出0x1000,第二次printf("%p", &fp)输出自身地址

  • 第二次调用中的&fp是取函数指针变量fp自身的存储地址,这是合法操作:fp作为变量在内存中占据固定空间(如栈上的某个位置),&fp就是该空间的地址,因此输出是确定且符合预期的。
  • 第一次输出0x1000依然是未定义行为的表现:当代码结构变化(加入&fp的操作),编译器的优化策略、栈的布局可能发生改变,导致未初始化的fp读取到栈上的另一残留值(0x1000可能是栈帧的边界值、编译器填充的占位值等)。这并非某种特殊机制,只是未定义行为下的随机结果。

关键结论

  • 永远不要使用未初始化的自动变量(包括函数指针),使用前必须为其赋值(比如指向某个合法函数,或赋值为NULL)。
  • %p格式符要求参数为void*类型,正确写法应为printf("%p", (void*)fp)和printf("%p", (void*)&fp),通过强制类型转换避免类型不匹配引发的未定义行为。

内容的提问来源于stack exchange,提问作者A_normal_guy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:50:05