为什么在读取double时,scanf()需要在"%lf"中使用L,而printf()不管其参数是double还是float都可以使用"%f"?
示例代码:
示例代码:
double d;
scanf("%lf", &d);
printf("%f", d);
double d;
scanf("%lf", &d);
printf("%f", d);
因为C语言会将浮点数在可变参数函数中提升为双精度类型,而指针不会被提升到任何类型,因此您应该使用%lf
、%lg
或%le
(在C99中使用%la
)来读取双精度浮点数。
自从 C99 以来,在C语言中,格式化标识符与浮点参数类型的匹配在 printf 和 scanf 函数之间是一致的。
%f
表示 float
类型%lf
表示 double
类型%Lf
表示 long double
类型恰好当传递的可变参数的类型是 float
时,这些参数会被隐式转换为 double
类型。这就是为什么在 printf 中,格式化标识符 %f
和 %lf
是等价和可互换的原因。在 printf 中可以将 %lf
用于 float
或者用 %f
来表示 double
。
但实际上没有必要这样做。不要使用 %f
来打印类型为 double
的变量。尽管在 C89/90 的时代很普遍,但这是个坏习惯。在 printf 中使用 %lf
来打印类型为 double
的变量,并将 %f
保留给 float
类型的参数。
printf
和scanf
之间的匹配是一致的。请注意,这并不意味着使用相同的格式说明符意味着由[f]printf()
写入的数据可以被[f]scanf()
读取。通常情况下,对于printf()
使用的相同格式说明符,在scanf()
中使用将不能成功读取数据。例如,printf()
的"%d"
格式说明符可以插入空格填充,但是在scanf()
调用中,相同的"%d"
格式说明符将跳过它们。 - Andrew Henlescanf
需要知道&d
所指向的数据大小才能正确地填充,而变长函数会将浮点数提升为双精度浮点数(不完全确定原因),所以printf
总是得到一个double
。
否则,scanf会认为您传递的是指向比double更小的float类型的指针,并返回一个不正确的值。
在C表达式中使用float或double值,得到的值都是double类型,因此printf无法区分。而指向double的指针必须明确地告知scanf与指向float的指针不同,因为指针指向的内容才是重要的。
float
值在表达式中会自动提升为 double
。但这个规则在标准 C 中被废弃了。通常情况下,在表达式中 float
不会被提升为 double
。只有当作为可变参数传递时,它才会被提升为 double
,这也是这种情况发生的原因。 - AnT stands with Russia
&
来“取地址”一个变量时,这个操作的结果是一个指向该变量在内存中存储位置的指针。正是这个指针被传递给了scanf
函数。 - zwol