double a = 3.1456;
int aa=2.0;
printf ("%f \n",a );
printf("%f \n",aa);
答案是3.145600 ,3.145599.
我尝试了不同的 a 值,并且输出 aa 似乎与 a 有某种关系。我很困惑。什么原因?~
~
~
~
printf( "%f", ... )
期望 adouble
作为参数,但 yu 传递一个整数。那是UB。在您的情况下, as sizeof(double) > sizeof(int)
,第二个 printf() 可能会从堆栈中读取一些字节,这些字节从上一次调用中“仍然存在”。如果您在两者之间添加了一些其他功能,结果将是其他东西。但是因为它是 UB,所以它没有被定义为这样,我发生的任何事情
Ingo Leonhardt说你的程序的行为是未定义的是正确的——在优化或不同的架构/编译器上输出不会是一致的。
但是,在这种情况下,您看到 3.1456 突变为 3.145599 的具体原因是可以解释的。可以推断,你的架构使用了 IEEE-754 8-byte double
s 和 4-byte little-endian int
s。最接近 3.1456 的 8 字节双精度的十六进制表示是:
0x40092a305532617c
其中符号为0
,指数字段为0x400
(表示指数为 1),尾数字段为0x92a305532617c
(表示 0x1.92a305532617c 的十六进制尾数)。如果你用 4 字节整数 2 覆盖它的低 4 字节,那么你会得到:
0x40092a3000000002
其符号和指数不变,但尾数已更改为 0x1.92a3000000002,即比原始值小 0x0.000005532617a。指数为 1,这表示 0x0.00000aa64c2f4 的差异,十进制为 ~0.000000634766。当你从 3.1456 中减去它时,你会得到 ~3.145599365234,它四舍五入为 3.145599。