printf 中 double
的正确格式说明符是什么?是 %f
还是 %lf
?我相信它是 %f
,但我不确定。
代码示例
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%lf"
是未定义的;在 C99 和 C11 库中,它被定义为与 "%f"
相同。
%lf
是 double
的正确格式说明符。但它在 C99 中变得如此。在此之前必须使用 %f
。
"%f"
是(或至少一个)正确的双精度格式。 没有 float
没有格式,因为如果您尝试将 float
传递给 printf
,它会在 printf
收到它之前被提升为 double
1。 "%lf"
在当前标准下也是可以接受的——如果后面跟着 f
转换说明符(以及其他),l
被指定为无效。
请注意,这是 printf
格式字符串与 scanf
(和 fscanf
等)格式字符串有很大不同的地方。对于输出,您将传递一个 值,当作为可变参数传递时,该值将从 float
提升到 double
。对于输入,您传递了一个未提升的 指针,因此您必须告诉 scanf
您是要读取 float
还是 double
,因此对于 scanf
, %f
表示您想阅读 float
,而 %lf
表示您想阅读 double
(而且,对于它的价值,对于 long double
,您可以将 %Lf
用于 printf
或scanf
)。
1. C99,第 6.5.2.2/6 节:“如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并且浮点类型的参数提升为双精度。这些被称为默认参数提升。”在 C++ 中,措辞有些不同(例如,它不使用“原型”一词),但效果是一样的:所有可变参数在被函数接收之前都经过默认提升。
给定 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 修订和更正.与上一版本相比的主要变化包括: %lf 转换说明符在 printf 7.19.6.1 中允许 fprintf 函数 7 长度修饰符及其含义是: l (ell) 指定 (...) 对后面的 a、A 没有影响、e、E、f、F、g 或 G 转换说明符。 L 指定后面的 a、A、e、E、f、F、g 或 G 转换说明符适用于 long double 参数。
为 fprintf
指定的相同规则适用于 printf
、sprintf
和类似函数。
7.19.6.2 fscanf 函数 11 长度修饰符及其含义为: l (ell) 指定 (...) 后面的 a、A、e、E、f、F、g 或 G 转换说明符适用于具有指向双精度类型指针的参数; 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 -> 双倍
%Lf -> 长双倍。
对于 fscanf
它是:
%f -> 浮动
%lf -> 双倍
%Lf -> 长双倍。
它可以是 %f
、%g
或 %e
,具体取决于您希望数字的格式。有关详细信息,请参阅 here。 l
修饰符在 scanf
和 double
中是必需的,但在 printf
中不需要。
l
(小写)修饰符用于整数类型(cplusplus.com/reference/clibrary/cstdio/printf),L
用于浮点类型。此外,L
修饰符需要 long double
,而不是普通的 double
。
printf
中对于 double
不需要 l
。
格式 %lf
是 double
的完全正确的 printf
格式,与您使用的完全一样。你的代码没有问题。
printf
中的格式 %lf
在 C 语言的旧(C99 之前)版本中不受支持,这在 printf
和 scanf
中的 double
格式说明符之间造成了表面上的“不一致”。这种表面上的不一致已在 C99 中得到修复。
您不需要在 printf
中将 %lf
与 double
一起使用。如果您愿意,也可以使用 %f
(%lf
和 %f
在 printf
中是等效的)。但在现代 C 中,更喜欢将 %f
与 float
一起使用,%lf
与 double
一起使用,以及 %Lf
与 long double
一起使用是非常有意义的,在 printf
和 scanf
中都是一致的。
scanf()
、"%f"
、"%lf"
匹配 float *, double *
,而不是最后一行暗示的 float, double
。
%Lf
(注意大写 L
)是 long doubles 的 format specifier。
对于普通的 doubles
,%e
、%E
、%f
、%g
或 %G
都可以。
%g
和 %G
有什么区别?
-Wall -Werror -pedantic
编译时g++
拒绝%lf
:error: ISO C++ does not support the ‘%lf’ gnu_printf format
l
是一个扩展。 C99/11 和 C++11 标准要求实现允许它。scanf
确实 想要由%lf
表示的double
:它抱怨说它期望float *
并发现double *
只有%f
。scanf
采用指向存储读取内容的位置的指针,因此 需要 知道所指向的空间有多大,而printf
采用值本身,并且“默认参数提升”意味着两者都以double
结尾,因此l
本质上是可选的。