C语言 使用printf时%f和%lf可以互换吗?[副本]

fruv7luv  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(193)

此问题已在此处有答案

What is the difference between %f and %lf in C?(4个答案)
12小时前关闭。
在www.example.com上的一篇文章中w3resource.com,我看到了以下代码:

double x, y;
pr1 = sqrt(pr1);
x = (-b + pr1)/(2*a);
y = (-b - pr1)/(2*a);
printf("Root1 = %.5lf\n", x);
printf("Root1 = %.5lf\n", y);

文章说取三个浮点数。但是在他们的解决方案(这个代码片段)中,他们使用了%lf说明符。为什么使用%lf而不是%f?我也可以使用%f而不是%lf来处理浮点数吗?
如果我使用float关键字而不是double,并使用%f,是否有任何问题?输出对我来说是一样的。

li9yvcax

li9yvcax1#

%fprintfscanf系列函数中有不同的含义:

  • printf中,%f%lf是等价的,并且两者都由double匹配。这是因为在可变参数函数中,当调用函数时,所有float参数都提升为double,因此在语言级别传递floatdouble没有区别。
  • scanf中,%f匹配float*%lf匹配double*,这种区别非常重要。使用错误类型的指针将导致未定义的行为。

您还可以使用cdecl+来更好地理解printfscanf调用。输出如下:

printf("Root1 = %.5lf\n", x)
Write "Root1 = "
Write a decimal double with lower-case infinity/NaN symbols
    precision: 5
Write "\n"

ARGUMENTS & EXPECTED TYPES
--------------------------
x (double)

当有疑问时,使用%f表示float,使用%lf表示double,即使在printf中,两者之间也没有区别。否则,您将在scanfprintf字符串之间引入无意义的不一致。

* 浮点数 * 注意事项

您可能对floatfloating-point number 的含义感到困惑。floatdoublelong double等是C中的浮点数。当文章中提到 * 浮点数 * 时,它们也可能意味着double_Decimal32_Float128等。

为什么scanf不像printf一样将float*升级为double*

这是不可能的,因为我们存储float的对象不能用于存储double

  • 在语言级别上,这将是一个strict aliasing violation
  • 在实现级别,我们将尝试存储例如8字节的double在一个float,其中包括四个字节,这是不可能的。
qkf9rpyu

qkf9rpyu2#

来自C标准(7.21.6.1 fprintf函数)

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

和(6.5.2.2函数调用)
7如果表示被调用函数的表达式有一个包含原型的类型,则参数被隐式转换为相应参数的类型,就像通过赋值一样,每个参数的类型都是其声明类型的非限定版本。函数原型声明符中的省略号表示法会导致参数类型转换在最后一个声明的参数之后停止。默认参数升级是对尾随参数执行的。
和/或
6如果表示被调用函数的表达式的类型不包括原型,则对每个参数执行整数提升,并且具有float类型的参数被提升为double。这些称为默认参数提升
使用长度修饰符l和转换说明符f只会让代码的读者感到困惑。它的使用会产生问题。代码的读者会认为代码的作者不知道长度修饰符没有效果,或者如果没有长度修饰符,printf(或fprintf)的调用确实会有未定义的行为,并且使用长度修饰符是必要的。
至于使用长度修饰符调用scanf,则函数处理float *double *类型的指针。也就是说,default参数promotions 不会应用于它们。所以要区分一个指针是指向float类型的对象还是指向double类型的对象,你必须使用长度修饰符l和转换说明符f以及double *类型的指针,或者不使用长度修饰符float *类型的指针。
在调用printf(或fprintf)时,对double类型的对象使用长度修饰符l只会使代码更难维护,因为例如,如果输出变量的类型将从double类型更改为float类型,则必须找到并更改使用该变量的所有printf调用。

相关问题