在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
没有格式,因为如果你尝试传递一个float
到printf
,它会在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
的值,对于printf
或scanf
,使用%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
指定的规则同样适用于printf
, sprintf
和类似的函数。
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
这取决于您希望如何格式化数字。 在这里看到更多的细节。 在scanf
, l
修饰符是必需的,但在printf
不能。
%Lf
(注意大写L
)是长打的格式说明符 。
对于普通的doubles
, %e
, %E
, %f
, %g
或%G
都可以。
用于double
的正确的printf
格式是%lf
,与您使用的完全相同。 你的代码没有问题。
printf
中的%lf
格式在旧版(C99之前的版本)中不被支持,这在printf
和scanf
double
格式说明符之间产生了表面“不一致”。 这个肤浅的不一致已经在C99中得到了修复。
所以在现代的C语言中,最好使用%f
和float
, %lf
使用double
, %Lf
使用printf
和scanf
long double
。
对于双重你可以简单地使用%lf
或者你可以根据你的喜好使用下面的任何一个
%e
或%E
为指数格式的值
%g
或%G
,对于正常或指数符号,取其大小更适合。
在这里阅读更多C中所有格式说明符的列表