假设我在C语言中有以下代码:
double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);
它从标准输入读取变量“ var”,然后在标准输出中两次打印“ var”。 我知道这是如何从标准输入读取双精度变量的,但我的问题是:
- 为什么可以使用%lf打印双精度?
- 为什么可以使用%f打印双精度?
- 哪个更好,更正确?
对于变长参数函数(例如printf
和scanf
),参数会被提升,比如较小的整数类型会被提升为int
,float
会被提升为double
。
scanf
接受指针类型的参数,因此提升规则不起作用。它必须使用 %f
来读取 float*
类型的值,使用 %lf
来读取 double*
类型的值。
printf
永远不会看到 float
类型的参数,因为 float
总是会被提升为 double
。格式说明符是 %f
。但是,C99 同时规定在 printf
中,%lf
和 %f
是相同的:
C99 §7.19.6.1 函数
fprintf
l
(小写字母 L)表示后面的d
、i
、o
、u
、x
、或X
转换说明符应用于一个long int
或unsigned long int
类型的参数;表示后面的n
转换说明符应用于一个long int
类型的指针;表示后面的c
转换说明符应用于一个wint_t
类型的参数;表示后面的s
转换说明符应用于一个wchar_t
类型的指针;或对后面的a
、A
、e
、E
、f
、F
、g
、或G
转换说明符没有影响。
当一个浮点数(float
)被传递给 printf
函数时,它会自动转换为双精度浮点数(double
)。这是“默认参数提升”(default argument promotions)的一部分,该机制适用于具有可变参数列表(包含 ...
)的函数,主要是由于历史原因。因此,“自然”的浮点数格式规定符 %f
必须与 double
类型的参数兼容。所以对于 printf
函数,%f
和 %lf
的规定符是相同的;它们都接收一个双精度浮点数类型的值。
在调用 scanf
函数时,传递的是指针而不是直接的值。指向 float
类型的指针不会被转换为指向 double
类型的指针(这是无法实现的,因为当你改变指针类型时,指向的对象不能改变)。因此,在使用 scanf
函数时,%f
的参数必须是指向 float
类型的指针,而 %lf
的参数必须是指向 double
类型的指针。
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]
所以您可能需要仔细检查您的标准是否支持该语法。
总之,我会建议您使用“%lf”进行阅读,并使用“%f”进行打印。
printf
函数中它们是相同的。 - Marounscanf
接受指针,无法提升,但printf
接受值,可以提升。就打印而言,我可能会使用%lf
,因为对于任何阅读您的代码的人来说,这更清晰。 - robbie_c