在带有 gcc 的 Linux 下会发生这种情况:编译器将 7.4 作为双精度传递,因为 test 原型仅在 main 之后定义。
0000000000400506 <main>:
400506: 55 push %rbp
400507: 48 89 e5 mov %rsp,%rbp
40050a: 48 83 ec 10 sub $0x10,%rsp
40050e: 48 b8 9a 99 99 99 99 movabs $0x401d99999999999a,%rax
400515: 99 1d 40
400518: bf 04 00 00 00 mov $0x4,%edi
40051d: 48 89 45 f8 mov %rax,-0x8(%rbp)
400521: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
400526: b8 01 00 00 00 mov $0x1,%eax
40052b: e8 07 00 00 00 callq 400537 <test>
400530: b8 00 00 00 00 mov $0x0,%eax
400535: c9 leaveq
400536: c3 retq
0x401d99999999999a 是你的 64 位双精度,即 7.4。 test 函数将该值解释为单精度数字(浮点数,如原型中指定),使用cvtss2sd(浮点数到双精度数转换)通过xmm0 将其传递给printf:
0000000000400537 <test>:
400537: 55 push %rbp
400538: 48 89 e5 mov %rsp,%rbp
40053b: 48 83 ec 10 sub $0x10,%rsp
40053f: f3 0f 11 45 fc movss %xmm0,-0x4(%rbp)
400544: f3 0f 11 4d f8 movss %xmm1,-0x8(%rbp)
400549: f3 0f 5a 45 fc cvtss2sd -0x4(%rbp),%xmm0
40054e: bf e4 05 40 00 mov $0x4005e4,%edi
400553: b8 01 00 00 00 mov $0x1,%eax
400558: e8 83 fe ff ff callq 4003e0 <printf@plt>
40055d: c9 leaveq
40055e: c3 retq
40055f: 90 nop
这只会将初始 64 位值的一小部分转换为打印到标准输出的实际双精度值,即 0x9999999a,产生接近 0 的结果。