为什么第一个和第三个printf工作方式如此不同?

Ash*_*ini 5 c printf

printf("line 5: %f\n",98);  //output is 0.000000
printf("line 6: %f\n",98.98); //output is 98.980000  
printf("line 5: %f\n",98);//though same as first printf statement but output is 98.979980
Run Code Online (Sandbox Code Playgroud)

虽然第一个和最后一个printf语句完全相同,但它们的输出不同.为什么?

因为当它期望浮动时,正在将一个int传递给printf,这就是为什么它工作很奇怪.但我的观点是为什么在最后一个打印声明中,它不是打印一些垃圾值或0,而是使用第二个printf语句的值,这就是打印的内容.

Jon*_*oni 5

正如其他人已经说过的那样,当它预期会导致未定义的行为时,传递intprintfdouble,并且任何事情都可能发生.你可能会感兴趣的原因,为什么程序打印98.979980在第三行,而不是一些随机数.

参数传递到printf堆栈上.当第2行传递98.98printf它时,它被推到堆栈上,首先是数字的最低部分.

然后printf返回,并在第三行再次调用它,现在98推入堆栈.在您的架构上,int类型似乎是32位; double类型的一半大小,所以这只覆盖98.98了早期堆栈的下半部分.98.98的上半部分仍在筹码中.

现在第三次调用从堆栈中printf读取a double.它读取的最重要的一半来自98.98早先在堆栈上的,而不太重要的一半来自二进制表示98; 这就是结果如此接近的原因98.98.由于98是如此小的数字,其最高有效位将为0,并且将最不重要的一半设置98.98为大多数为零会给出较小的数字.

如果第3行使用的数字设置为1,则会得到超过的结果98.98.例如,-1的二进制表示将其所有位设置为1,您将获得:

printf("line 2: %f\n", 98.98); # 98.98
printf("line 3: %f\n", -1);    # 98.980042
Run Code Online (Sandbox Code Playgroud)

如果编译器使用64位整数,或者首先传递double具有最高有效部分的s,或者使用寄存器而不是堆栈来传递参数,则会得到非常不同的结果.


小智 4

因为您的程序调用了未定义的行为。 98类型为int,但%f需要 a float(或double,由于默认升级规则)。

因此,由于printf()UB 当转换说明符的类型和实际类型不匹配时,它所做的任何事情都没有合理的解释。