简体   繁体   English

Scanf / Printf双变量C.

[英]Scanf/Printf double variable C

Let's say I have this following bit of code in C: 假设我在C中有以下代码:

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

It reads from stdin variable 'var' and then prints twice in stdout 'var'. 它从stdin变量'var'读取,然后在stdout'var'中打印两次。 I understand that's how you read a double variable from stdin, but my questions are: 我理解你是如何从stdin读取双变量的,但我的问题是:

  1. Why can you print a double with %lf? 为什么你可以用%lf打印双倍?
  2. Why can you print a double with %f? 为什么你可以用%f打印双倍?
  3. Which one is better and correct to use? 使用哪一种更好更正确?

For variable argument functions like printf and scanf , the arguments are promoted, for example, any smaller integer types are promoted to int , float is promoted to double . 对于像printfscanf这样的变量参数函数,会提升参数,例如,任何较小的整数类型都会提升为intfloat会提升为double

scanf takes parameters of pointers, so the promotion rule takes no effect. scanf接受指针参数,因此促销规则不起作用。 It must use %f for float* and %lf for double* . 它必须使用%f表示float*%lf表示double*

printf will never see a float argument, float is always promoted to double . printf永远不会看到float参数, float总是被提升为double The format specifier is %f . 格式说明符是%f But C99 also says %lf is the same as %f in printf : 但是C99还说%lfprintf %f相同:

C99 §7.19.6.1 The fprintf function C99§7.19.6.1的fprintf功能

l (ell) Specifies that a following d , i , o , u , x , or X conversion specifier applies to a long int or unsigned long int argument; l (ell)指定以下diouxX转换说明符适用于long intunsigned long int参数; that a following n conversion specifier applies to a pointer to a long int argument; 以下n转换说明符适用于指向long int参数的指针; that a following c conversion specifier applies to a wint_t argument; 以下c转换说明符适用于wint_t参数; that a following s conversion specifier applies to a pointer to a wchar_t argument; 以下s转换说明符适用于指向wchar_t参数的指针; or has no effect on a following a , A , e , E , f , F , g , or G conversion specifier. 对后续的aAeEfFgG转换说明符没有影响。

When a float is passed to printf , it is automatically converted to a double . float传递给printf ,它会自动转换为double This is part of the default argument promotions , which apply to functions that have a variable parameter list (containing ... ), largely for historical reasons. 这是默认参数提升的一部分,它适用于具有可变参数列表(包含... )的函数,主要是出于历史原因。 Therefore, the “natural” specifier for a float , %f , must work with a double argument. 因此, float的“自然”说明符%f必须使用double参数。 So the %f and %lf specifiers for printf are the same; 所以printf%f%lf说明符是相同的; they both take a double value. 他们都采取double价值。

When scanf is called, pointers are passed, not direct values. 调用scanf ,会传递指针,而不是直接值。 A pointer to float is not converted to a pointer to double (this could not work since the pointed-to object cannot change when you change the pointer type). 指向float的指针不会转换为指向double的指针(由于指向对象在更改指针类型时无法更改,因此无法工作)。 So, for scanf , the argument for %f must be a pointer to float , and the argument for %lf must be a pointer to double . 因此,对于scanf%f的参数必须是指向float的指针,而%lf的参数必须是指向double的指针。

As far as I read manual pages, scanf says that 'l' length modifier indicates (in case of floating points) that the argument is of type double rather than of type float, so you can have 'lf, le, lg'. 至于我阅读手册页,scanf说'l'长度修饰符指示(在浮点的情况下)参数是double类型而不是float类型,所以你可以有'lf,le,lg'。

As for printing, officially, the manual says that 'l' applies only to integer types. 至于打印,正式,手册说'l'仅适用于整数类型。 So it might be not supported on some systems or by some standards. 因此,某些系统或某些标准可能不支持它。 For instance, I get the following error message when compiling with gcc -Wall -Wextra -pedantic 例如,在使用gcc -Wall -Wextra -pedantic编译时,我收到以下错误消息

a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]

So you may want to doublecheck if your standard supports the syntax. 因此,如果您的标准支持语法,您可能需要重新检查。

To conclude, I would say that you read with '%lf' and you print with '%f'. 总而言之,我会说你用'%lf'阅读并用'%f'打印。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM