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

使用printf将指针转为double时出现异常行为的原因排查

未解引用double指针用printf("%f")打印时,输出受之前printf的double值影响的原因

原本想演示忘记解引用double指针的后果:用printf("%f", pd)(而非*pd)打印double *pd类型指针,预期得到指针地址对应的double值,却发现之前打印的任意double值都会影响该未解引用指针的输出结果。

示例程序

#include <stdio.h>

int main() {
    double d = 123.456, *pd = &d;

    printf("%f ", *pd); // 第一次打印
    printf("%f\n", pd);

    return 0;
}

不同场景的输出

  • 正常运行输出:

123.456000 123.456000

  • 注释第一次打印后的输出:

0.000000

  • 将第一次打印改为printf("%f ", 555.555);后的输出:

555.555000 555.555000

运行环境:Ubuntu 22.04,GCC版本11.4.0,编译命令:

$ gcc -O0 example.c -o example

原因分析

这是由x86_64架构下的可变参数函数调用约定和浮点数传递规则导致的:

  • 在x86_64系统中,浮点数参数默认通过SSE寄存器(如%xmm0、%xmm1)传递,而整数、指针这类参数通过通用寄存器(如%rdi、%rsi)传递。
  • printf是可变参数函数,它完全依赖格式字符串来解析参数来源。当你用printf("%f", pd)时,%f告诉printf要从SSE寄存器中读取double值,但实际上你传递的指针pd是放在通用寄存器里的,printf找不到对应SSE寄存器的有效数据,就会读取之前留在SSE寄存器里的残留值——也就是上一次printf调用传入的double值。
  • 若注释掉第一次打印,程序运行到该printf前未使用SSE寄存器传递浮点数,寄存器初始值为0,因此输出0.000000。

你误以为指针和double都是8字节就会被直接当作double读取,但核心问题是调用约定区分了不同类型参数的传递通道,printf只会按格式字符串指定的通道去取值,而非直接从内存或通用寄存器中读取字节解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:02:46