奇怪的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