在printf中,双精度浮点数的正确格式说明符
在printf中,双精度浮点数的正确格式说明符
在printf中double的正确格式说明符是什么?是%f
还是%lf
?我认为应该是%f
,但我不确定。
代码示例
#include int main() { double d = 1.4; printf("%lf", d); // Is this wrong? }
鉴于 C99 标准(即 N1256 草案),规则取决于函数类型:fprintf(printf,sprintf,...)或 scanf。
以下是相关部分的摘录:
前言
本版的出版取消并替代了第一版 ISO/IEC 9899:1990,该版由 ISO/IEC 9899/COR1:1994、ISO/IEC 9899/AMD1:1995 和 ISO/IEC 9899/COR2:1996 进行修改和更正。
相对于上一版,主要的变化包括:
- 允许在 printf 中使用 %lf 转换说明符
7.19.6.1 函数 fprintf
7 长度限定符及其含义如下:
l(小写 L) 表示(...)对后续的 a、A、e、E、f、F、g 或 G 转换说明符没有影响。
L 表示后续的 a、A、e、E、f、F、g 或 G 转换说明符应用于 long double 类型的参数。
相同的规则适用于 printf、sprintf 等函数。
7.19.6.2 函数 fscanf
11 长度限定符及其含义如下:
l(小写 L)表示(...)后续的 a、A、e、E、f、F、g 或 G 转换说明符应用于指向 double 的指针类型参数;
L 表示后续的 a、A、e、E、f、F、g 或 G 转换说明符应用于指向 long double 的指针类型参数。
12 转换说明符及其含义如下:
a、e、f、g 匹配可选符号的浮点数(...)
14 转换说明符A、E、F、G和X也有效,并与相应的小写字母说明符a、e、f、g和x行为相同。
简而言之,对于fprintf
,指定了以下说明符和相应的类型:
%f
-> 双精度浮点数(double)%Lf
-> 长双精度浮点数(long double)。
对于fscanf
,它是:
%f
-> 单精度浮点数(float)%lf
-> 双精度浮点数(double)%Lf
-> 长双精度浮点数(long double)。
""%f"
" 是一个(或至少一个)正确的双精度浮点数格式。不存在一个用于 float
的格式,因为如果您尝试将一个 float
传递给 printf
,则在 printf
接收它之前,它将被提升为 double
。"%lf"
在当前标准下也是可以接受的,l
指定在 f
转换说明符之后没有任何效果(其中包括其他转换说明符)。
需要注意的是,在这一点上,printf
格式字符串与 scanf
(以及 fscanf
等)格式字符串大不相同。对于输出,您正在传输一个值,当作为可变参数传递时,它会从 float
提升为 double
。对于输入,您正在传递一个指针,该指针不会提升,因此您必须告诉 scanf
您想要读取一个 float
还是 double
,因此对于 scanf
,%f
意味着您想要读取一个 float
,而 %lf
表示您想要读取一个 double
(对于 long double
,您无论是使用 printf
还是 scanf
,都需要使用 %Lf
)。
1. C99,§6.5.2.2/6:“如果表示被调用函数的表达式的类型不包括原型,则在每个参数上执行整数提升,并将类型为float的参数提升为double。这些被称为默认参数升级。”在C++中措辞略有不同(例如,它不使用“原型”一词),但效果相同:在它们被函数接收之前,所有可变参数都要经过默认提升。