2015-02-07 95 views
-3
#include <stdio.h> 
int main() 
{ 
    printf("%f",5); 
} 

此代码打印0.000000。任何人都可以解释为什么会这样。float的访问说明符不像预期的那样表现

+0

因为你显示INT为双 - 这是定义你想怎么逗号后许多地方显示 - 看看如何显示由printf()的方法,双/浮在谷歌:) – 2015-02-07 19:45:54

+4

难道你没有编译器警告你的' %f'-int不匹配? – Biffen 2015-02-07 19:48:41

+0

尝试调查自己..举例说,[“%f”,5.0] [“%f”,.5] [“%.5f”,5] [“%。5f”,5.0] – 2015-02-11 10:37:58

回答

4

这是因为在你的榜样,5是一个整数,而不是浮动。因此,当您将其传递给格式为%fprintf时,您会收到未定义的行为。要使其成为浮点数,请使用浮点数(5.0)进行声明。这会给你预期的输出。

实施例:

#include <stdio.h> 
int main() 
{ 
    printf("%f", 5.0); 
} 

输出:

5.000000 
5

%f格式需要double参数,您传递的是int。这是未定义的行为,任何事情都可能发生。你幸运的是,发生的只是0.00000的印刷。

在C中,可变参数函数不知道在呼叫站点传递给它们的参数的类型。在printf的情况下,他们只能信任格式字符串以提供该信息。任何好的编译器都应该警告参数的类型是否与编译时(在编译时已知)格式字符串不匹配,我很惊讶你没有。该函数的实现可以依赖已应用的默认参数促销,但仅此而已。

在实践中,两种常见的情况下是参数被传递到堆栈,在此情况下int5这是在调用位置被推将被解释为一个64位double,或参数通过寄存器传递,在这种情况下,printf函数将从浮点寄存器得到一个double的值,该值在调用位置处未设置,并且包含上次使用时留在那里的值。

3

这被称为未定义的行为,因为“%f”需要一个浮点数或双精度值,但您给它的整数为5

未定义的行为意味着编译器可以处理任何合法的事情来处理这种情况。

来解决,你有三种选择:

  1. printf("%i", 5)
  2. printf("%f", 5.0)
  3. printf("%f", (double) 5)
2

%f是用于double类型(或float,其被自动地在可变参数列表升为double)的格式说明,但是'通过它int。正如其他答复者已经正确指出的那样,这是未定义的行为。

但是为什么输出为零而不是一些其他垃圾值?这需要对最常见的floating-point format有一点了解。

最可能发生的情况是您的(可能)32位int值被零扩展为64位double值,以这些额外的32个零位填充符号位,位指数,以及有效位的前20位。这导致denormal的值非常接近零,以至于定点%f格式将其舍入到0.00000。使用%e%g格式可能会显示一个小但非零的值。

同样,这仅仅是一个实施的细节,和不同的C实现可以得到不同的输出,或导致段故障。

什么你可能意味着写的或者是

  • printf("%f", 5.0)(使用的%f格式正确的数据类型),或
  • printf("%d", 5)(使用为int类型的正确格式字符串)

防止意外使用不匹配printf调用如printf("%f", 5),启用编译器警告(例如,使用GCC的-Wall选项),并在编译程序时注意它们。

+0

zero-extension在普通的IA-32 ABI中不会发生(32位被推入,64位被读取,没有零扩展),并且在普通的x86-64 ABI中不会发生(获得第一个浮点参数从'xmm0'),所以我不确定你的意思。 – 2015-02-07 20:15:06