为什么printf()不输出这个整数作为浮点数?

我有这个代码:

#include <stdio.h> int main() { int i = 12345; printf("%f", i); return 0; } 

printf()将输出0.000000,不应该printf()将i包含的位作为浮点数来解释?

从技术上讲,这是未定义的行为

您应该使用联合来执行此操作,并使用%e而不是%f来打印它,因为它是一个很小的数字:

 #include <stdio.h> union int2float { int a; float b; }; int main() { union int2float tmp; tmp.a = 12345; printf("%e\n", tmp.b); return 0; } 

这导致1.729903e-41

%.100f你会得到0.0000000000000000000000000000000000000000172990295420898667405534417057140146406548336724655872023410作为输出。

这在技术上是不确定的行为,所以任何事情都可能发生,例如@Art在他的回答中所描述的。

这个答案因此是一个解释,如果你试图打印12345作为浮动假设printf确实看到正确的32位值会发生什么。

我们来分析一下你想表示的数字的二进制表示。

使用http://www.h-schmidt.net/FloatConverter/IEEE754.html我们可以看到十进制&#x6570;12345具有以下32位表示:

 decimal 12345 hexadecimal 0x00003039 

bit-to-bit转换为IEEE-754浮点32位值,表示:

 float 1.7299E-41 

让我们尝试打印它:

 #include <stdio.h> int main() { printf("%f\n", 1.7299E-41); return 0; } 

这打印:

 0.000000 

现在让我们来阅读printf手册页,如下所示: http : //linux.die.net/man/3/printf

f,F

double参数被四舍五入,并在样式[ – ] ddd.ddd中转换为十进制表示法,其中小数点后面的位数等于精度规格。 如果精度丢失,则取6; 如果精度显式为零,则不显示小数点字符。 如果出现小数点,至少有一个数字出现在它之前。

1.7299E-41值不能用默认精度的这个标志表示,所以你得到的结果的确是正确的值。

最有可能的原因printf不把i的位解释为一个浮点数是printf根本看不到i 。 我怀疑你正在运行x86_64或类似的平台,其参数传递给寄存器中的函数。 通常printf会将你的int解释为你给它的任何格式说明符。 但是函数的浮点参数在x86_64上处理方式不同,并被放入不同的寄存器。 所以你得到0作为输出的原因是, printf在格式化字符串之后取出第一个浮点参数,而不是第一个通用寄存器并打印出来。 由于您在调用printf之前没有使用任何浮点寄存器,因此它们很可能从程序启动时被清零。

您可以尝试以下实验:

 #include <stdio.h> int main(int argc, char **argv) { printf("%f\n", 17.42); printf("%f\n", 0x87654321); return 0; } 

我得到这个输出:

 $ ./foo 17.420000 17.420000 

说了这么多,唯一正确的答案是:这是未定义的行为,不要这样做。 但有趣的是看到底下发生了什么。

如果你想深入研究Linux / MacOS / * BSD, 这个3.2.3节描述了如何传递参数给函数(包括可变参数函数printf)。 Windows做的事情略有不同,但在这种情况下,在Windows上的结果是完全一样的。 在Linux / MacOS / * BSD上的printf希望当你的调用在%rsi (Windows上的%rdx )中传递参数时,参数将被打印在%xmm0 (Windows的%xmm1 )中。

当然,如果我对x86_64错了,不管我说的是什么,看看@SirDarius的答案,因为这适用于许多(尤其是较老的)体系结构。 如果你使用的是alpha,sparc,powerpc,arm等,那么你就是自己的。 使用int调用printf一次,使用float调用一次,反汇编已编译的代码并查看参数是如何传递的。

如果你想打印一个int作为float,将其转换为:

 printf("%f", (float)i); 

printf()知道格式化字符串(及其计数)之后的参数的数据类型的唯一方法是通过读取格式字符串。 内存中整数的表示形式与浮点数不同。 您以一个整数的格式传递printf()数据,但它采用浮点数的格式。 这就是为什么你在控制台中得到垃圾。 您可以通过类型转换来纠正此问题。

 printf("%f", (float) i); 

当您使用%f格式说明符时,您必须使用float变量并打印该值。 但你已经宣布i为整数,并试图打印使用%f它会打印一些价值。 因为它是一个整数你必须使用%d指定符。 在printf %f中将搜索float变量。 但是不会有浮点变量,所以它会打印一些值。

打印时可以输入转换整数值。 printf("%f",(float)i);

为了让i作为float类型,你需要做类型转换。

您可以使用

 printf("%f", (float)i); 

例。

 float myFloat; int myInt; myFloat = (float)myInt ; // Type casting 

尝试这个

 int i = 12345; printf("%.2f", i/1.0f);