2011-11-05 112 views
3

我执行以下代码奇怪的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

在此先感谢

+0

@Shahbaz现在,它不是标签C++了,真 – MrRap

回答

12

这是因为你的printf格式说明符不符合你通过它:

9/5int类型。但printf预计float

所以,你需要或者将它转换为浮动或作出任何面值的浮动:

printf("%f\n", (float)9/5); 
printf("%f\n", 9./5); 

至于为什么你要0.0,这是因为printf()正在读1二进制表示(整数)并将其打印为float。这恰好是一个非常小的非规格化值,非常接近0.0

编辑:还有一些类型的促销可变参数。

在可变参数函数中,float被提升为double。因此在这种情况下printf()实际上需要一个持有double的64位参数。但是你只传递了一个32位的操作数,所以它实际上是从堆栈中读取了一个额外的32位(在这种情况下它恰好为0) - 甚至还有更多未定义的行为。

+1

当被问及警告时,像GCC这样的编译器会发现(使用'gcc -Wall') –

+0

无法保证printf的参数在堆栈上传递(或者甚至有堆栈)。你不知道*它在读什么。 –

+0

@Stephen佳能:什么是替代品?可以举个例子吗? – jfs

0

内用不正确的格式说明printf是UB。

printf("%f %f %zu %d\n", (float)9/5, 4.0, sizeof(float), sizeof(int)); 

给出正确的输出。

+1

如何9/5计算为0 ??! – Shahbaz

+0

9/5是1,你在想5/9。类型不匹配是正确的。 – Kevin

+0

@Shahbaz:我的错。编辑帖子。 –

0

如果您使用GCC构建,则应该打开-Wall的所有警告,并仔细阅读它们。

你之所以“奇怪”的输出为您违反printf先天条件(参数传递,其类型不匹配的格式规范),一旦你做到了,printf自由为所欲为,包括崩溃,打印垃圾或熔化CPU。

3

让我们看看什么在位级别是怎么回事:

  • 你计算9/5,这两个数字int - >此计算结果为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个字节。这与上面的问题是一样的。

+0

但是当我使用float b = 9/5然后打印b的值时,为什么我不这样做。它在这种情况下打印5。你能解释一下吗? – chinmayaposwalia

+0

5 ?!这不可能。你需要给我看一段代码,然后我会告诉你 – Shahbaz

0

9/5是一个整数,但您试图用“%f”打印它。这是问题的根源。切换到9.0/5或“%d”,你会得到正确的答案。

0

(float)9/5只投9次而不是9/5的结果。所以/操作在这一点上不是一个整数操作。 (浮动)(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; 
} 

给出:

[email protected]:~/proj/c=>./pf 
1.000000 4.000000 4 4