C语言 printf 中 double 的正确格式说明符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4264127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:10:46  来源:igfitidea点击:

Correct format specifier for double in printf

cfloating-pointprintfdoubleformat-specifiers

提问by Leopard

What is the correct format specifier for doublein printf? Is it %for is it %lf? I believe it's %f, but I am not sure.

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

Code sample

代码示例

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}

回答by Jerry Coffin

"%f"is the (or at least one) correct format for a double. There isno format for a float, because if you attempt to pass a floatto printf, it'll be promoted to doublebefore printfreceives it1. "%lf"is also acceptable under the current standard -- the lis specified as having no effect if followed by the fconversion specifier (among others).

"%f"是(或至少一种)双精度格式的正确格式。有一个没有格式的float,因为如果你试图传递一个floatprintf,它会被提升到doubleprintf接受它1"%lf"在当前标准下也是可以接受的——l如果后面跟有f转换说明符(等等),则被指定为无效。

Note that this is one place that printfformat strings differ substantially from scanf(and fscanf, etc.) format strings. For output, you're passing a value, which will be promoted from floatto doublewhen passed as a variadic parameter. For input you're passing a pointer, which is not promoted, so you have to tell scanfwhether you want to read a floator a double, so for scanf, %fmeans you want to read a floatand %lfmeans you want to read a double(and, for what it's worth, for a long double, you use %Lffor either printfor scanf).

请注意,这是printf格式字符串与scanf(和fscanf等)格式字符串有很大不同的地方。对于输出,您正在传递一个value,当作为可变参数传递时,它将从floatto提升double。对于输入你传递一个指针,这是不松口,所以你必须要告诉scanf你是否想读一个float或一个double,所以scanf%f你想读的手段float%lf你想读的手段double(和,为它的值得,对于 a long double,您%Lf用于printfscanf)。



1. C99, §6.5.2.2/6: "If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions." In C++ the wording is somewhat different (e.g., it doesn't use the word "prototype") but the effect is the same: all the variadic parameters undergo default promotions before they're received by the function.

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

回答by mloskot

Given the C99standard (namely, the N1256draft), the rules depend on the function kind: fprintf (printf, sprintf, ...) or scanf.

鉴于C99标准(即N1256草案),规则取决于函数类型:fprintf (printf, sprintf, ...) 或 scanf。

Here are relevant parts extracted:

以下是提取的相关部分:

Foreword

This second edition cancels and replaces the first edition, ISO/IEC 9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996. Major changes from the previous edition include:

  • %lfconversion specifier allowed in printf

7.19.6.1 The fprintffunction

7The length modifiers and their meanings are:

l(ell) Specifies that (...) has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.

LSpecifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.

前言

此第二版取消并替代了第一版 ISO/IEC 9899:1990,并由 ISO/IEC 9899/COR1:1994、ISO/IEC 9899/AMD1:1995 和 ISO/IEC 9899/COR2:1996 修正和修正。与上一版相比,主要变化包括:

  • %lf允许的转换说明符 printf

7.19.6.1fprintf功能

7长度修饰符及其含义是:

l(ell) 指定 (...) 对后面的 a、A、e、E、f、F、g 或 G 转换说明符没有影响。

L指定后面的 a、A、e、E、f、F、g 或 G 转换说明符适用于 long double 参数。

The same rules specified for fprintfapply for printf, sprintfand similar functions.

对于指定的规则同样fprintf适用于printfsprintf和类似的功能。

7.19.6.2 The fscanffunction

11The length modifiers and their meanings are:

l(ell) Specifies that (...) that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to double;

LSpecifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to long double.

12The conversion specifiers and their meanings are: a,e,f,g Matches an optionally signed floating-point number, (...)

14The conversion specifiers A, E, F, G, and X are also valid and behave the same as, respectively, a, e, f, g, and x.

7.19.6.2fscanf功能

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 相同。

The long story short, for fprintfthe following specifiers and corresponding types are specified:

长话短说,fprintf指定了以下说明符和相应的类型:

  • %f-> double
  • %Lf-> long double.
  • %f-> 双
  • %Lf-> 长双。

and for fscanfit is:

因为fscanf它是:

  • %f-> float
  • %lf-> double
  • %Lf-> long double.
  • %f-> 浮动
  • %lf-> 双
  • %Lf-> 长双。

回答by vitaut

It can be %f, %gor %edepending on how you want the number to be formatted. See herefor more details. The lmodifier is required in scanfwith double, but not in printf.

它可以是%f%g或者%e取决于您希望如何格式化数字。请参阅此处了解更多详情。该l修正是必需的scanfdouble,但不是在printf

回答by AnT

Format %lfis a perfectly correct printfformat for double, exactly as you used it. There's nothing wrong with your code.

Format%lf是完全正确的printf格式double,与您使用的完全相同。你的代码没有任何问题。

Format %lfin printfwas not supported in old (pre-C99) versions of C language, which created superficial "inconsistency" between format specifiers for doublein printfand scanf. That superficial inconsistency has been fixed in C99.

C 语言的旧版本(C99 之前)不支持格式%lfin printf,这在doubleinprintfscanf. 这种表面上的不一致已在 C99 中得到解决。

You are not required to use %lfwith doublein printf. You can use %fas well, if you so prefer (%lfand %fare equivalent in printf). But in modern C it makes perfect sense to prefer to use %fwith float, %lfwith doubleand %Lfwith long double, consistently in both printfand scanf.

您不需要使用%lfwith doublein printf%f如果您愿意,您也可以使用(%lf并且%f在 中等效printf)。但是在现代 C 中,更喜欢在两者和中一致地使用%fwith float%lfwithdouble%Lfwith是完全合理的。long doubleprintfscanf

回答by Frédéric Hamidi

%Lf(note the capital L) is the format specifierfor long doubles.

%Lf(注意是大写L)是格式说明长双打

For plain doubles, either %e, %E, %f, %gor %Gwill do.

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