正确的格式说明符用于printf中的double


480

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

代码样例

#include <stdio.h>

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

19
如果您使用的是C89库,"%lf"则未定义;在C99和C11库中,它定义为与相同"%f"
pmg 2012年

1
您的变体与以往一样正确。%lf是的正确格式说明符double。但是在C99中变得如此。在此之前,必须使用%f
AnT

Answers:


624

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

请注意,这是printf格式字符串与scanf(和fscanf等)格式字符串本质上不同的地方。对于输出,你传递一个,这将被提升floatdouble时,作为可变参数参数传递。对于输入,您要传递一个不会提升的指针,因此您必须告诉scanf您是否要读取a float或a double,因此对于scanf%f表示您想读取a,float并且%lf您想读取a double(并且,其含义是值得,为long double你使用%Lf的两种printfscanf)。


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


8
请注意,使用以下g++%lf-Wall -Werror -pedanticerror: ISO C++ does not support the ‘%lf’ gnu_printf format
命令进行

2
@kynan:如果是这样(至少假设使用g ++的当前版本),那是g ++中的错误。对于C89 / 90和C ++ 98/03,允许l是扩展。C99 / 11和C ++ 11标准要求实现允许它。
杰里·科芬

1
奇怪的是,scanf 确实要用double表示%lf:它抱怨期望float *并找到double *了just %f
埃里克·丹德

1
@JerryCoffin g ++仍默认为g ++ 98模式
MM

5
@EricDand这是因为scanf需要在何处存储它进行读取,因此需要知道有多大的空间被指向-AT是,而printf所采用的值本身,而“默认参数提升”是指两端向上为doubleS,因此l是本质上是可选的。
TripeHound

63

给定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转换说明符(...)适用于类型指针为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 ->双
  • %Lf ->长双。

因为fscanf它是:

  • %f ->浮动
  • %lf ->双
  • %Lf ->长双。

25

可以是%f%g或者%e取决于您希望数字如何格式化。有关更多详细信息,请参见此处。该l修正是必需的scanfdouble,但不是在printf


1
-1 :(l小写)修饰符用于整数类型(cplusplus.com/reference/clibrary/cstdio/printf),并且L用于浮点类型。另外,L修饰符期望a long double,而不是plain double
user470379 2011年

10
user470379:那么我的答案矛盾在哪里?我不是说for l不需要。printfdouble
vitaut 2011年

15

格式完全符合您使用的%lf正确printf格式double。您的代码没有错。

C语言的旧版本(C99之前的版本)不支持format %lfin printf,这会在doublein printf和的格式说明符之间造成表面上的“不一致” scanf。这种表面上的不一致已在C99中修复。

您不需要使用%lfdoubleprintf%f如果您愿意,也可以使用(%lf%f等效printf)。但是,在现代的C,这是绝对意义上喜欢使用%ffloat%lfdouble%Lflong double,持续两printfscanf


随着scanf()"%f""%lf"匹配float *, double *,而不是float, double由最后一行暗示。
chux-恢复莫妮卡

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.