我执行了以下代码
#include <stdio.h>
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
提前致谢
答案 0 :(得分:12)
这是因为您的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位(在这种情况下恰好是零) - 甚至更多未定义的行为。
答案 1 :(得分:3)
让我们看一下比特级别的内容:
您计算9/5,两个数字int
- &gt;这评估为1(再次int
)(比如32位),即:
0000 0000 0000 0000 0000 0000 0000 0001
您将其作为printf
printf
读取我上面写的那个数字并将其打印出来,好像它是用IEEE 754编码的那样。结果几乎为0。您可以看到here转化:
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
需要 double ,即8个字节。这与上面的问题相同。
答案 2 :(得分:0)
在printf
中使用不正确的格式说明符是UB。
printf("%f %f %zu %d\n", (float)9/5, 4.0, sizeof(float), sizeof(int));
给出正确的输出。
答案 3 :(得分:0)
如果您使用GCC构建,则应使用-Wall
打开所有警告并仔细阅读。
你得到“奇怪”输出的原因是你违反了printf
的先决条件(传递其类型与格式规范不匹配的参数),一旦你做了,printf
可以自由做任何想做的事情,包括崩溃,打印垃圾或熔化你的CPU。
答案 4 :(得分:0)
9/5是整数,但您尝试使用“%f”打印它。这是问题的根源。切换到9.0 / 5或“%d”,您将得到正确的答案。
答案 5 :(得分:0)
(float)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 <stdio.h>
#include <stdlib.h>
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