假设我在 C 中有以下代码:
double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);
它从标准输入变量“var”中读取,然后在标准输出“var”中打印两次。我知道这就是您从标准输入读取双变量的方式,但我的问题是:
- 为什么可以用 %lf 打印双精度?
- 为什么可以使用 %f 打印双精度?
- 哪一个更好更正确使用?
printf
对于像and之类的可变参数函数scanf
,参数被提升,例如,任何较小的整数类型被提升为int
,float
被提升为double
。
scanf
带指针参数,所以提升规则无效。它必须使用%f
forfloat*
和%lf
for double*
。
printf
永远不会看到float
争论,float
总是被提升为double
。格式说明符是%f
. 但 C99 也说与中%lf
相同:%f
printf
C99 §7.19.6.1
fprintf
函数
l
(ell) 指定后面的d
,i
,o
,u
,x
, orX
转换说明符适用于long int
orunsigned long int
参数;后面的n
转换说明符适用于指向long int
参数的指针;以下c
转换说明符适用于wint_t
参数;后面的s
转换说明符适用于指向wchar_t
参数的指针;或对后面a
的 ,A
,e
,E
,f
,F
,g
, 或G
转换说明符没有影响。
当 afloat
传递给 时printf
,它会自动转换为 a double
。这是默认参数提升的一部分,它适用于具有可变参数列表(包含...
)的函数,主要是出于历史原因。因此,a 的“自然”说明符float
必须%f
与double
参数一起使用。所以%f
and%lf
说明符printf
是一样的;他们都double
取值。
调用时scanf
,传递的是指针,而不是直接值。指向的指针float
不会转换为指向的指针double
(这不起作用,因为当您更改指针类型时,指向的对象无法更改)。因此,对于scanf
,参数 for%f
必须是指向 的指针float
,而参数 for%lf
必须是指向 的指针double
。
就我阅读手册页而言,scanf 表示“l”长度修饰符表示(在浮点的情况下)参数是 double 类型而不是 float 类型,因此您可以使用“lf, le, lg”。
至于打印,官方说 'l' 仅适用于整数类型。因此,某些系统或某些标准可能不支持它。例如,我在编译时收到以下错误消息gcc -Wall -Wextra -pedantic
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]
因此,您可能需要仔细检查您的标准是否支持该语法。
总而言之,我会说您使用 '%lf' 阅读并使用 '%f' 打印。