在printf中修正double的格式说明符

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

代码示例

 #include <stdio.h> int main() { double d =1.4; printf("%lf", d); //is this wrong? } 

"%f"是双精度格式(或至less一个)。 float没有格式,因为如果你尝试传递一个floatprintf ,它会在printf收到它之前被提升为double 1 。 在当前的标准下, "%lf"也是可以接受的 – 如果后面跟着f转换说明符(除其他外), l被指定为无效。

请注意,这是printf格式string与scanf (和fscanf等)格式string大不相同的地方。 对于输出,你传递一个 ,当作为一个可变parameter passing时,这个将从float提升到double 。 对于input来说,你传递的是一个没有被提升的指针 ,所以你必须告诉scanf你要读取一个float还是一个double ,所以对于scanf%f表示你想读一个float%lf表示你想要读取一个double (以及对于long double的值,对于printfscanf ,使用%Lf )。


1. C99,§6.5.2.2/ 6:“如果表示被调用函数的expression式的types不包含原型,则对每个参数执行整数提升,并将具有floattypes的参数提升为double。这些被称为默认参数促销。“ 在C ++中,措辞有些不同(例如,它不使用“原型”这个词),但效果是相同的:所有可变参数在被函数接收之前都进行默认促销。

鉴于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。 以前版本的重大变化包括:

  • %lf允许在printf转换说明符

7.19.6.1 fprintf函数

7长度修饰符及其含义如下:

l (ell)指定(…)对后续的a,e,e,f,f,g或G转换说明符无效。

L指定以下a,A,e,E,f,F,g或G转换说明符适用于长双参数。

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

7.19.6.2 fscanf函数

11长度修饰符及其含义如下:

l (ell)指定(…)后面的a,A,e,E,f,F,g或G转换说明符应用于指针types为double的参数;

L指定以下a,A,e,E,f,F,g或G转换说明符应用于指针types为long double的参数。

12转换说明符及其含义如下:a,e,f,g匹配一个可选的有符号浮点数,(…)

14转换说明符A,E,F,G和X也是有效的,分别表示a,e,f,g和x。

长话短说,为fprintf指定了以下说明符和相应的types:

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

对于fscanf来说是这样的:

  • %f – >浮动
  • %lf – > double
  • %Lf – >长双。

它可以是%f%g%e这取决于您希望如何格式化数字。 在这里看到更多的细节。 在scanfl修饰符是必需的,但在printf不能。

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

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

用于double的正确的printf格式是%lf ,与您使用的完全相同。 你的代码没有问题。

printf中的%lf格式在旧版(C99之前的版本)中不被支持,这在printfscanf double格式说明符之间产生了表面“不一致”。 这个肤浅的不一致已经在C99中得到了修复。

所以在现代的C语言中,最好使用%ffloat%lf使用double%Lf使用printfscanf long double

对于双重你可以简单地使用%lf或者你可以根据你的喜好使用下面的任何一个

%e%E为指数格式的值

%g%G ,对于正常或指数符号,取其大小更适合。

在这里阅读更多C中所有格式说明符的列表