您可能正在 64 位 x86 架构上运行此应用程序。在此架构上,浮点参数在 XMM 寄存器中传递,而整数参数在通用寄存器中传递。看系统 V AMD64 ABI 约定 http://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI_convention.
Because %f
需要一个浮点值:
printf("i is %f \n",i);
打印 XMM0 寄存器中的值,该值恰好是k
较早分配且未分配i
传入 RSI 寄存器。组装看起来像这样:
movl $.LC1, %edi # "k is %f \n"
movsd .LC0(%rip), %xmm0 # float k = 2
call printf
movl $1, %esi # int i = 1
movl $.LC2, %edi # "i is %f \n"
call printf # prints xmm0 because of %f, not esi
如果您像这样重新排序作业:
int i = 1;
printf("i is %f \n",i);
float k = 2;
printf("k is %f \n",k);
它打印:
i is 0.000000
k is 2.000000
因为XMM0寄存器的值恰好为0。
[Update]它也可以在 32 位 x86 上重现。在这个平台上printf()
基本上是铸造int*
to double*
然后读到double
。让我们修改一下示例以便于查看:
int main() {
float k = 2;
int i = -1;
printf("k is %f \n",k);
printf("i is %f \n",i,i);
}
64位输出:
k is 2.000000
i is 2.000000
32位输出:
k is 2.000000
i is -nan
也就是说,2int
值为 -1 的 s 看起来像double
0xffffffffffffffff 这是一个NaN
value.