ChatGPT解决这个技术问题 Extra ChatGPT

printf 中 double 的正确格式说明符

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

代码示例

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}
如果您被 C89 库困住,"%lf" 是未定义的;在 C99 和 C11 库中,它被定义为与 "%f" 相同。
您的变体与以往一样正确。 %lfdouble 的正确格式说明符。但它在 C99 中变得如此。在此之前必须使用 %f

J
Jerry Coffin

"%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 用于 printfscanf)。

1. C99,第 6.5.2.2/6 节:“如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并且浮点类型的参数提升为双精度。这些被称为默认参数提升。”在 C++ 中,措辞有些不同(例如,它不使用“原型”一词),但效果是一样的:所有可变参数在被函数接收之前都经过默认提升。


请注意,使用 -Wall -Werror -pedantic 编译时 g++ 拒绝 %lferror: ISO C++ does not support the ‘%lf’ gnu_printf format
@kynan:如果是这样(至少假设g ++的当前版本),那是g ++中的一个错误。对于 C89/90 和 C++98/03,允许 l 是一个扩展。 C99/11 和 C++11 标准要求实现允许它。
奇怪的是,scanf 确实 想要由 %lf 表示的 double:它抱怨说它期望 float * 并发现 double * 只有 %f
@JerryCoffin g++ 仍然默认为 g++98 模式
@EricDand 那是因为 scanf 采用指向存储读取内容的位置的指针,因此 需要 知道所指向的空间有多大,而 printf 采用值本身,并且“默认参数提升”意味着两者都以 double 结尾,因此 l 本质上是可选的。
u
user694733

给定 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 指定的相同规则适用于 printfsprintf 和类似函数。

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 -> 长双倍。


t
ti7

它可以是 %f%g%e,具体取决于您希望数字的格式。有关详细信息,请参阅 herel 修饰符在 scanfdouble 中是必需的,但在 printf 中不需要。


-1:l(小写)修饰符用于整数类型(cplusplus.com/reference/clibrary/cstdio/printf),L 用于浮点类型。此外,L 修饰符需要 long double,而不是普通的 double
user470379:那我的回答哪里矛盾了?我不是说过在 printf 中对于 double 不需要 l
A
AnT stands with Russia

格式 %lfdouble 的完全正确的 printf 格式,与您使用的完全一样。你的代码没有问题。

printf 中的格式 %lf 在 C 语言的旧(C99 之前)版本中不受支持,这在 printfscanf 中的 double 格式说明符之间造成了表面上的“不一致”。这种表面上的不一致已在 C99 中得到修复。

您不需要在 printf 中将 %lfdouble 一起使用。如果您愿意,也可以使用 %f%lf%fprintf 中是等效的)。但在现代 C 中,更喜欢将 %ffloat 一起使用,%lfdouble 一起使用,以及 %Lflong double 一起使用是非常有意义的,在 printfscanf 中都是一致的。


使用 scanf()"%f""%lf" 匹配 float *, double *,而不是最后一行暗示的 float, double
F
Frédéric Hamidi

%Lf(注意大写 L)是 long doublesformat specifier

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


%g%G 有什么区别?
@yanpas,指数符号的小写/大写。
抱歉,%g 和 %G 确实输出 E 符号。他们还在不同的情况下输出 INF 和 inf