printf中double的正确格式说明符

printf中double的正确格式说明符是什么?是%f还是%lf?我相信是%f,但我不确定。

代码示例

#include <stdio.h>


int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
1355600 次浏览

它可以是%f%g%e,这取决于你想要的数字格式。详见在这里。在scanfdouble中需要l修饰符,但在printf中不需要。

%Lf(注意大写的L)是长双打格式说明符

对于普通的doubles,或者%e%E%f%g%G都可以。

"%f"是(或至少一个)double类型的正确格式。float没有格式,因为如果你试图将float传递给printf,它会在printf接收到float0之前被提升到double"%lf"在当前标准下也是可以接受的——如果后面跟着f转换说明符,则l被指定为无效。

请注意,这是printf格式字符串与scanf(和fscanf等)格式字符串有本质区别的地方。对于输出,您传递的是scanf7,当作为可变参数传递时,它将从float提升到double。对于输入,你传递了一个scanf8,这是不提升的,所以你必须告诉scanf你是否想读一个floatdouble,所以对于scanf%f意味着你想读一个floatscanf1意味着你想读一个double(并且,为了它的价值,对于scanf3,你使用scanf4为printfscanf)。


< p > <子> 1. C99,§6.5.2.2/6:“如果表示被调用函数的表达式的类型不包括原型,则对每个实参执行整数提升,类型为float的实参将提升为double。这些被称为默认参数提升。”在c++中,措辞有些不同(例如,它不使用“prototype”这个词),但效果是一样的:所有可变参数在被函数接收之前都会进行默认的提升。 < / sub > < / p >
对于C99标准(即N1256草案),规则依赖于 函数类型:fprintf (printf, sprintf,…)或scanf.

以下是相关部分摘录:

前言

本第二版取消并取代了由ISO/IEC 9899/COR1:1994、ISO/IEC 9899/AMD1:1995和ISO/IEC 9899/COR2:1996修订和修正的第一版ISO/IEC 9899:1990。 与前一版本相比的主要变化包括:

  • printf中允许的%lf转换说明符

7.19.6.1 fprintf函数

长度修饰符及其含义是:

l (ell)指定(…)对后面的a, a, e, e, f, f, g或g转换说明符没有影响。

l指定a, a, e, e, f, f, g或g后面的转换说明符应用于长双精度实参。

fprintf指定的规则同样适用于printfsprintf和类似的函数。

7.19.6.2 fscanf函数

长度修饰符及其含义是:

l (ell)指定(…)a, a, e, e, f, f, g或g转换说明符后面的a应用于类型指针指向double的实参;

l指定a, a, e, e, f, f, g或g转换后的a 说明符应用于类型指针指向长double的实参 转换说明符及其含义是: a,e,f,g匹配一个有符号浮点数,(…)

转换说明符A、E、F、G和X也是有效的,它们的行为分别与A、E、F、G和X相同。

长话短说,对于fprintf,指定了以下说明符和相应的类型:

  • %f ->双
  • %Lf ->长双。

对于fscanf,它是:

  • %f ->浮动
  • %lf ->双
  • %Lf ->长双。

格式%lf是一个完全正确的printf格式的double,完全像你使用它。你的代码没有问题。

旧版本(c99之前)的C语言不支持printf中的%lf格式,这在printf中的doublescanf的格式说明符之间造成了表面上的“不一致”。这种表面上的不一致在C99中得到了修复。

您不需要在printf中使用%lfdouble。如果你喜欢的话,你也可以使用%f (%lf%fprintf中是等价的)。但在现代C语言中,更喜欢使用%ffloat%lfdoubledouble1和double2,在printfdouble4中都是一致的,这是完全有意义的。