为什么在printf()只需加上“%f”就可以的情况下,scanf()需要双精度的“%lf”吗?


179

为什么在读取a 时scanf()需要lin“ ,而无论其参数是a 还是a 时都可以使用” “ ?%lfdoubleprintf()%fdoublefloat

示例代码:

double d;
scanf("%lf", &d);
printf("%f", d);

1
我不明白您在这里所说的POINTER是什么意思。在scanf中,我们仅传递&variable(ie)地址,所以指针在哪里

7
@deetchanya在C语言中,当您使用一元运算&符“获取”变量的地址时,该操作的结果是指向变量在内存中的存储位置的指针。是传递给的指针scanf
zwol 2013年

Answers:


207

因为C会将带有可变参数的函数的浮点数提升为双精度。指针不松口任何东西,所以你应该使用%lf%lg%le(或%la在C99)在双打阅读。


26

由于С99用C格式说明和浮点参数类型之间的匹配是之间是一致的printfscanf。它是

  • %f 对于 float
  • %lf 对于 double
  • %Lf 对于 long double

碰巧的是,当类型float的参数作为可变参数传递时,此类参数被隐式转换为type double。这就是为什么在printf格式说明符中%f%lf它们是等效且可互换的。在中,printf您可以%lffloat%f与“交叉使用” double

但是没有理由在实践中实际进行。不要使用类型%f为的printf参数double。这是一个普遍的习惯,可追溯到C89 / 90年代,但这是一个坏习惯。使用%lfprintfdouble和不断%f预留float参数。


1
我会说%f在printf 中使用 是一个好习惯,因为这样您的代码将始终有效,而%lf如果编译器没有C99兼容库,则使用可能会失败。不幸的是,这种情况确实发生在现实中。
MM

由于С99用C格式说明和浮点参数类型之间的匹配是之间是一致的printfscanf 注意,这并不意味着使用相同的格式说明符意味着[f]printf()可以用读取由a写入的数据[f]scanf()。在一般情况下,使用相同的格式说明对于scanf()已使用的printf()不会成功地读取数据。例如,可以由被插入空间填充prinf()"%d"格式说明将由相同被跳过"%d"的格式说明scanf()呼叫。
安德鲁·亨利

16

scanf需要知道所指向的数据的大小&d以正确填充它,而可变参数函数会将浮点数提升为两倍(不完全确定为什么),所以printf总是得到a double


1
可变参数函数非常脆弱,因为它需要能够知道传递给它的所有参数的确切类型和大小,并且不能在编译时强制执行。如果变量的类型错误,将读取错误的值。如果大小错误,则之后的所有变量也会被误读。如果可以通过两种不同大小的浮标,则将引起各种令人讨厌且容易遗漏的问题。
mwfearnley

7

因为否则scanf会认为您正在传递一个指向小于双精度数大小的float的指针,并且它将返回错误的值。


2

在C表达式中使用float或double值将导致值始终是double,因此printf无法分辨出差异。而指向double的指针必须显式地向scanf发出信号,以不同于float指针,因为该指针所指向的是重要的。


5
浮子被转换为一个双在这种情况下,因为自变量是一个可变长度的自变量列表的一部分,浮子并不总是转换成双打中C.
罗伯特Gamble的

1
在标准版的C语言float值中double,表达式会自动提升为。该规则在标准C中已被放弃。通常,float它不会double在表达式中得到提升。它仅double当作为可变参数传递时才被提升到这种情况。
AnT 2015年
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.