double
的正确格式说明符是什么?是%f
还是%lf
?我相信是%f
,但我不确定。代码示例
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
#1 楼
"%f"
是双精度格式的(或至少一种)正确格式。 float
没有格式,因为如果您尝试将float
传递给printf
,则它将在double
收到之前被提升为printf
1。 "%lf"
在当前标准下也是可以接受的-如果l
转换说明符(除其他外)后面指定为f
,则无效。请注意,这是
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节:“如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,而将类型为float的参数提升为双精度。称为默认参数提升。”在C ++中,措词有些不同(例如,它不使用单词“ prototype”),但效果是相同的:所有可变参数在接受函数之前都经过默认提升。
评论
请注意,使用-Wall -Werror -pedantic进行编译时,g ++拒绝%lf:错误:ISO C ++不支持'%lf'gnu_printf格式
– kynan
2013年6月10日12:16
@kynan:如果是这样(至少假设当前版本为g ++),那是g ++中的错误。对于C89 / 90和C ++ 98/03,允许l是扩展。 C99 / 11和C ++ 11标准要求实现允许它。
–杰里·科芬(Jerry Coffin)
2013年6月10日13:16
奇怪的是,scanf确实希望用%lf表示双精度型:它抱怨它期望float *并只用%f找到了double *。
–埃里克·丹
2014年11月14日在7:23
@JerryCoffin g ++仍默认为g ++ 98模式
– M.M
2015年7月19日,0:33
@EricDand这是因为scanf会使用指向存储所读取内容的指针,因此需要知道所指向的空间有多大,而printf会自己获取值,而“默认参数提升”则意味着两者最终都加倍,因此l本质上是可选的。
– TripeHound
15年8月26日在13:58
#2 楼
给定C99标准(即N1256草案),规则取决于函数类型:fprintf(printf,sprintf,...)或scanf。
这里提取了相关部分:
前言
本第二版取消并代替经ISO / IEC 9899 / COR1修订和更正的第一版ISO / IEC 9899:1990 :1994,ISO / IEC 9899 / AMD1:1995和ISO / IEC 9899 / COR2:1996。
与上一版相比,主要变化包括:
%lf
中允许的printf
转换说明符7.9.6.1
fprintf
函数7长度修饰符及其含义为:
l (ell)指定(...)对后面的a,A,e,E,f,F,g或G转换说明符无效。
L指定后面的a, A,e,E,f,F,g或G转换说明符适用于长双精度参数。
为
fprintf
指定的相同规则也适用于printf
,sprintf
和类似功能。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
-> double %Lf
-> long double。#3 楼
可以是%f
,%g
或%e
,具体取决于您希望数字如何格式化。有关更多详细信息,请参见此处。在l
和scanf
中需要double
修饰符,但在printf
中不是必需的。评论
-1:l(小写)修饰符用于整数类型(cplusplus.com/reference/clibrary/cstdio/printf),而L则用于浮点类型。此外,L修饰符期望长双倍,而不是普通双倍。
–user470379
2011年1月19日19:28
user470379:那么我的答案在哪里呢?我不是说过,printf中不需要l来加倍。
–维生素
2011年1月20日上午10:09
#4 楼
格式%lf
是与printf
完全正确的double
格式,与您使用的完全相同。您的代码没有问题。旧的(C99之前)C语言版本不支持
%lf
的printf
格式,这在double
和printf
的scanf
格式说明符之间造成了表面的“不一致”。这种表面上的不一致已在C99中修复。 您无需在
%lf
中将double
与printf
一起使用。如果愿意,也可以使用%f
(%lf
和%f
在printf
中是等效的)。但是在现代C语言中,最好在%f
和float
中始终使用%lf
和double
,%Lf
和long double
和printf
和scanf
一致。评论
使用scanf()时,“%f”,“%lf”匹配浮点数*,双精度*,而不是浮点数,最后一行所暗示的是double。
–chux-恢复莫妮卡
19年12月8日在13:09
#5 楼
%Lf
(请注意大写的L
)是长双精度的格式说明符。对于普通
doubles
,%e
,%E
,%f
,%g
或%G
都可以。评论
%g和%G有什么区别?
– yanpas
16 Jan 10 '13 at 13:29
@yanpas,分别为指数符号的小写/大写。
–FrédéricHamidi
16年1月10日在14:18
抱歉,%g和%G确实输出E符号。他们在不同情况下也会输出INF和inf
– yanpas
16 Jan 10 '14在14:26
评论
如果您使用的是C89库,则“%lf”是未定义的;在C99和C11库中,它定义为与“%f”相同。您的变体与以往一样正确。 %lf是double的正确格式说明符。但是在C99中变得如此。在此之前,必须使用%f。