C中%f和%lf有什么区别?

时间:2014-09-16 04:46:59

标签: c

我在C书的C示例中看到了这两个参数,但作者并没有详细说明两者之间的区别。我知道%f指定浮点数应该取而代之。我试着查看这个,但很难找到这个w符号。那么%lf呢?

4 个答案:

答案 0 :(得分:22)

对于scanf%f读取float%lf读入double

对于printf:在C99及更高版本中,它们都是相同的,并且会打印floatdouble。在C89中,%lf导致了未定义的行为,尽管它是将其视为%f的常见扩展。

printf中一个说明符可用于两种不同类型的原因是默认参数提升;当用于调用函数而不匹配函数原型中的参数时,类型float的参数将被提升为double。因此printf只会在任何一种情况下看到double

答案 1 :(得分:10)

printf家族没有区别。对于7.21.6.1 The fprintf function修饰符(我的粗体),ISO C11标准(以下所有参考均来自C11),部分/7l段状态:

  

指定以下d,i,o,u,x或X转换说明符适用于long int或unsigned long int参数;以下n转换说明符适用于指向long int参数的指针;以下c转换说明符适用于wint_t参数;以下s转换说​​明符适用于指向wchar_t参数的指针; 或对后续a,A,e,E,f,F,g或G转换说明符没有影响。

它不需要修改f说明符的原因是因为该说明符已经表示double,来自该段/8同一节:

  

表示浮点数的双参数在样式...

中转换为十进制表示法

这与以下事实有关:函数原型中椭圆后面的参数根据6.5.2.2 Function calls/7进行默认参数提升:

  

...函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数之后停止。默认参数提升是在尾随参数上执行的。

由于printf(实际上整个printf族 - 类似函数)被声明为带有省略号表示法的int printf(const char * restrict format, ...);,因此该规则适用于此处。 6.5.2.2 Function calls部分/6

部分介绍了默认参数提升
  

如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有float类型的参数提升为double。这些是称为默认参数促销。


对于scanf系列,它要求使用double而不是float。第7.21.6.2 The fscanf function /11节:

  

指定以下d,i,o,u,x,X或n转换说明符适用于类型指向long int或unsigned long int的参数; 以下a,A,e,E,f,F,g或G转换说明符适用于类型指针为double的参数; 或后续的c,s或[转换说明符]适用于带有指向wchar_t的类型指针的参数。

这会修改该部分的/12段,指出%f

  

匹配可选带符号的浮点数,无穷大或NaN,其格式与strtod函数的主题序列的预期格式相同。相应的参数应为指向浮动的指针。

答案 2 :(得分:1)

printf()正常忽略%lf中的宽度修饰符。或者,为了更准确,%f需要双倍 - varargs将始终将浮动参数提升为双倍。

答案 3 :(得分:0)

对于使用printf系列函数的输出,%f和%lf指示符含义相同; l被忽略。两者都需要一个对应的double类型的参数-但是float类型的参数被提升为double类型,这就是为什么没有单独的float类型说明符的原因。 (此促销仅适用于可变参数函数,例如printf以及不带原型声明的函数,一般不适用于函数调用。)对于long double类型,正确的格式说明符为%Lf。

对于使用scanf系列功能的输入,浮点格式说明符为%f,%lf和%Lf。这些要求分别指向类型为float,double和long double的对象的指针。 (因为参数是指针,所以没有将float转换为double的功能。可以将float值提升为double,但是无法将float *指针提升为double *,因为指针必须指向实际的float对象。 )

但是要小心使用带有数字输入的scanf函数。没有定义的溢出检查,并且如果输入超出了类型的范围,则程序的行为是不确定的。为了安全起见,将输入读入字符串,然后使用诸如strtod之类的东西将其转换为数字值。 (请参阅文档以了解如何检测错误。)