奇怪的printf输出

时间:2011-11-05 17:36:39

标签: c floating-point printf

我执行了以下代码

#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

提前致谢

6 个答案:

答案 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从参数中获取32位数据并将其打印为浮点数。
  • 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));

不会产生您期望的结果,原因是参数4int,这是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