为什么以下代码在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之间的任何内容。
答案 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
值。