a是double,printf(“%d”,a);在IA32和IA32-64中的工作方式不同

时间:2016-06-13 02:04:11

标签: c memory printf ieee-754 stdio

为什么以下代码在IA-32和x86-64上完全不同?

#include    <stdio.h>
int main()  {
     double a   =   10;
     printf("a  =   %d\n",  a);
     return 0;
}

在IA-32上,结果始终为0。 但是,在x86-64上,结果可以是MAX_INT和MIN_INT之间的任何内容。

2 个答案:

答案 0 :(得分:1)

%d实际上用于打印int。从历史上看,d代表“十进制”,与八进制o和十六进制x形成对比。

要打印double,您应该使用%e%f%g

使用错误的格式说明符会导致undefined behaviour,这意味着可能发生任何事情,包括意外结果。

答案 1 :(得分:0)

将参数传递给与格式字符串中的格式说明符不匹配的printf()是未定义的行为...并且对于未定义的行为,任何事情都可能发生,并且结果不一定从一个实例到另一个 - 所以应该避免。

至于为什么你看到x86(32位)和x86-64之间的区别,可能是因为在每种情况下传递参数的方式不同。

在x86的情况下,printf()的参数很可能在堆栈上传递,在4字节边界上对齐 - 所以当printf()处理%d说明符时,它会读取来自堆栈的4字节int,实际上是来自a的低4字节。由于a为10,因此这些字节没有设置位,因此它们被解释为int值为0.

在x86-64的情况下,printf()的参数都在寄存器中传递(尽管如果有足够的,有些会在堆栈上)......但是传递了double个参数在不同于int参数的寄存器中(例如%xmm0而不是%rsi)。因此,当printf()尝试处理int参数以匹配%d说明符时,它会从另一个寄存器中获取a传入的a,并使用任何垃圾值保留在寄存器中而不是int的低字节,并将其解释为一些垃圾pod install值。