47

假设我在 C 中有以下代码:

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

它从标准输入变量“var”中读取,然后在标准输出“var”中打印两次。我知道这就是您从标准输入读取双变量的方式,但我的问题是:

  1. 为什么可以用 %lf 打印双精度?
  2. 为什么可以使用 %f 打印双精度?
  3. 哪一个更好更正确使用?
4

3 回答 3

59

printf对于像and之类的可变参数函数scanf,参数被提升,例如,任何较小的整数类型被提升为intfloat被提升为double

scanf带指针参数,所以提升规则无效。它必须使用%fforfloat*%lffor double*

printf永远不会看到float争论,float总是被提升为double。格式说明符是%f. 但 C99 也说与中%lf相同:%fprintf

C99 §7.19.6.1fprintf函数

l(ell) 指定后面的d, i, o, u, x, orX转换说明符适用于long intorunsigned long int参数;后面的n转换说明符适用于指向long int参数的指针;以下c转换说明符适用于wint_t参数;后面的s转换说明符适用于指向wchar_t参数的指针;或对后面a的 , A, e, E, f, F, g, 或G转换说明符没有影响。

于 2013-11-13T13:12:47.743 回答
13

当 afloat传递给 时printf,它会自动转换为 a double。这是默认参数提升的一部分,它适用于具有可变参数列表(包含...)的函数,主要是出于历史原因。因此,a 的“自然”说明符float必须%fdouble参数一起使用。所以%fand%lf说明符printf是一样的;他们都double取值。

调用时scanf,传递的是指针,而不是直接值。指向的指针float不会转换为指向的指针double(这不起作用,因为当您更改指针类型时,指向的对象无法更改)。因此,对于scanf,参数 for%f必须是指向 的指针float,而参数 for%lf必须是指向 的指针double

于 2013-11-13T12:53:30.153 回答
6

就我阅读手册页而言,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' 打印。

于 2013-11-13T11:33:47.327 回答