在 printf 中,double
的正确格式说明符是什么?是 %f
还是 %lf
?我认为应该是 %f
,但我不确定。
代码示例
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
在 printf 中,double
的正确格式说明符是什么?是 %f
还是 %lf
?我认为应该是 %f
,但我不确定。
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%f"
是双精度浮点数的(至少之一)正确格式。并不存在浮点数的格式,因为如果你尝试将浮点数传递给 printf
,它会在 printf
接收它之前被提升为双精度浮点数1。根据当前标准,"%lf"
也是可以接受的。如果后面跟着 f
转换说明符(以及其他一些),则指定的 l
不起作用。printf
格式字符串与 scanf
(以及 fscanf
等)格式字符串有很大不同的地方之一。对于输出,您传递的是一个 值,当作为可变参数传递时,该值将从 float
升级为双精度浮点数。对于输入,您传递的是一个 指针,它不会被提升,因此必须告诉 scanf
您要读取一个 float
还是一个 double
。因此,对于 scanf
,%f
表示您要读取一个 float
,%lf
表示您要读取一个 double
(值得一提的是,对于 long double
,无论是用于 printf
还是 scanf
,都使用 %Lf
)。
1. C99,§6.5.2.2/6:“如果表示被调用函数的表达式具有不包括原型的类型,则执行整数提升,并将类型为 float 的参数提升为 double。这些被称为默认参数提升。”在 C++ 中,措辞有些不同(例如,它不使用“原型”一词),但效果相同:所有可变参数在被函数接收之前都会进行默认提升。
-Wall -Werror -pedantic
编译时,g++
会拒绝使用%lf
:error: ISO C++ does not support the ‘%lf’ gnu_printf format
。 - kynanl
是一种扩展。C99/11和C++11标准要求实现必须允许其使用。 - Jerry Coffinscanf
确实希望用%lf
表示double
类型:如果只用%f
,它会抱怨它期望得到float *
而不是double *
。 - Eric Dandscanf
需要指向存储读取内容的位置的指针,因此必须知道被指向的空间有多大;而printf
则直接取值本身,并且“默认参数提升”意味着它们都成为了double
,所以l
实际上是可选的。 - TripeHound前言
本次修订版取代了第一版 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
及类似函数,适用与 fprintf
相同的规则。
7.19.6.2 函数
fscanf
11 长度修饰符及其含义如下:
l (小写字母 ell) 指定 (...) 后续的 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
-> 浮点型%lf
-> 双精度浮点型%Lf
-> 长双精度浮点型。根据希望数字格式化的方式,它可以是%f
、%g
或%e
。更多细节请见此处。在使用double
时,scanf
需要使用l
修饰符,但在printf
中则不需要。
l
(小写)修饰符用于整数类型(http://www.cplusplus.com/reference/clibrary/cstdio/printf/),而`L`用于浮点类型。此外,`L`修饰符期望一个`long double,而不是普通的
double`。 - user470379printf
打印 double
类型时需要使用 l
。 - vitautprintf
函数,浮点类型的长度修饰符 l
会被忽略,因为浮点参数总是会被提升为 double 类型。Jerry Coffin 的回答包含更多信息。 - Hari%lf
是一个完全正确的 printf
格式,可以用于 double
类型,就像您使用它一样。您的代码没有任何问题。
%lf
在旧版(C99 之前)的 C 语言中不支持,在 printf
中为 double
指定格式说明符和在 scanf
中的表现形式之间表面上存在 "不一致性"。这种表面上的不一致性已经在 C99 中得到了修复。
在 printf
中,您不需要使用 %lf
来表示 double
。如果您愿意,也可以使用 %f
(%lf
和 %f
在 printf
中是等价的)。但在现代 C 中,最好在 printf
和 scanf
中都一致地使用 %f
来表示 float
、%lf
来表示 double
、%Lf
来表示 long double
。
scanf()
函数时,"%f"
和 "%lf"
分别匹配 float *
和 double *
,而不是最后一行所暗示的 float
和 double
。 - chux - Reinstate Monica
"%lf"
是未定义的;在 C99 和 C11 库中,它被定义为与"%f"
相同。 - pmg%lf
是double
的正确格式说明符。但这是在 C99 中才成为标准。在此之前,必须使用%f
。 - AnT stands with Russia