奇怪的printf输出
我执行了以下代码
#include int main() { printf("%f\n", 9/5); }
输出: 0.000000
为什么不1
?
如果我写printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int));
然后输出是1.800000 0.000000 4 59
为什么不1.800000 4 4 4
在我的机器上, sizeof (float)
是4
提前致谢
这是因为你的printf
格式说明符与你传递的不匹配:
9/5
的类型为int
。 但是printf
希望有一个float
。
因此,您需要将其强制转换为浮点数或将文字转换为浮点数:
printf("%f\n", (float)9/5); printf("%f\n", 9./5);
至于为什么你得到0.0
,这是因为printf()
正在读取1
(整数)的二进制表示并将其打印为float
。 这恰好是一个非常接近0.0
的小的非规范化值。
编辑:在varargs上也有类型推广的东西。
在vararg函数中, float
被提升为double
。 因此,在这种情况下, printf()
实际上需要一个64位参数保持一个double
。 但是你只传递了一个32位的操作数,所以它实际上从栈中读取了额外的32位(在这种情况下恰好为0) – 甚至更多未定义的行为。
让我们看一下比特级别的内容:
-
你计算9/5,两个数字都是
int
– >这个计算结果为1(再次为int
)(比如32位),它是:0000 0000 0000 0000 0000 0000 0000 0001
-
你推它作为
printf
参数 - 告诉printf从参数中获取32位数据并将其打印为浮点数。
-
printf
读取我上面写的那个数字并将其打印出来,好像它是用IEEE 754编码的那样。结果几乎为0。
你可以在这里看到转换:
0000 0000 0000 0000 0000 0000 0000 0001
评估为
1.4012984e-45
至于为什么
printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int));
不会产生你所期望的,原因是参数4
是一个int
,它是4个字节(在你的机器上)。 由于参数提升, %f
需要一个8字节的双精度。 这与上面的问题相同。
在printf
使用不正确的格式说明符是UB。
printf("%f %f %zu %d\n", (float)9/5, 4.0, sizeof(float), sizeof(int));
给出正确的输出。
如果使用GCC构建,则应使用-Wall
打开所有警告并仔细阅读。
你得到“奇怪”输出的原因是你违反了printf
的前提条件(传递其类型与格式规范不匹配的参数),一旦你这样做, printf
可以随意做任何事情,包括崩溃,打印垃圾,或融化你的CPU。
9/5是整数,但您尝试使用“%f”打印它。 这是问题的根源。 切换到9.0 / 5或“%d”,您将得到正确的答案。
(浮动)9/5只投射9而不是9/5的结果。 所以/ operation在这一点上不是整数运算。 (float)(9/5)将给出结果1.00000。
尝试编译所有警告,它可能会告诉你很多错误。
例如在64位Linux系统上,用gcc -Wall编译我得到:
pf.c: In function 'main': pf.c:6:2: warning: format '%f' expects argument of type 'double', but argument 3 has type 'int' [-Wformat] pf.c:6:2: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat] pf.c:6:2: warning: format '%d' expects argument of type 'int', but argument 5 has type 'long unsigned int' [-Wformat]
如上所述,您需要正确的格式说明符。 使用正确的格式说明符和转换给出:
#include #include int main(int argc, char **argv) { printf("%f %f %lu %lu\n",(float)(9/5),(float)4,sizeof(float),sizeof(int)); return 0; }
得到:
snits@perelman:~/proj/c=>./pf 1.000000 4.000000 4 4