使用 %f 但获取“format %f expects type double”

Using %f but get "format %f expects type double"

提问人:dargaud 提问时间:9/26/2023 最后编辑:Jabberwockydargaud 更新时间:9/30/2023 访问量:120

问:

除非我累了,否则我不明白以下警告。我不确定编译器基于什么(它是使用 Microchip 的 XC16 作为 dsPIC33 微控制器的 MPLAB X 6)。

float test=5.5;
printf("%f\n", test);
warning: format '%f' expects type 'double', but argument 2 has type 'float'

通常用于浮点和双精度,对吧? 不存在,所以我怎么能让这个警告消失而不做%f%lf%hfprintf("%f\n", (double)test)

我的问题与为什么“printf”中没有定义“float”的说明符有关?

C 浮点 嵌入式 printf

评论

3赞 Some programmer dude 9/26/2023
实际上,对于 vararg 函数,就像所有小于 应该提升为 .因为 和 之间没有区别。这似乎是一个误报,除非编译器不执行 到 的提升,在这种情况下,编译器是不正确的。printfdoubledoubleprintf%f%lftestdouble
1赞 Robert Harvey 9/26/2023
无论如何,如果您简单地转换为 .testdouble
3赞 Eric Postpischil 9/26/2023
@RobertHarvey:接受的答案的第一句话说为什么接受一个论点,并且一个论点会自动转换为 .它没有回答关于为什么编译器抱怨参数被传递的问题。%fdoublefloatdoublefloat
1赞 Andrew Henle 9/26/2023
@thebusybee 这不是对这个问题的欺骗。不可能将 a 传递给 varargs 函数,例如在符合标准的 C 中,因为 a 将被提升到 ,因此警告是无意义的。这看起来像一个非标准编译器,或者一个有错误的编译器。floatprintf()floatdouble
1赞 Jabberwocky 9/26/2023
致所有骗子:这绝对不是骗子,即使乍一看像是骗子。

答:

2赞 Lundin 9/27/2023 #1

这是一个编译器错误。MPLAB 编译器因其非常差的 C 标准合规性而臭名昭著。在Microchip论坛上,有很多非常古老的帖子报告了同样的问题(示例)。

正如注释中所指出的,是一个可变参数函数,传递给它的所有参数都受制于称为“默认参数升级”的东西,在这种情况下,这意味着传递的参数在传递给 时总是会隐式提升到。printffloatdoubleprintf

因此,由于这些强制性的默认参数提升,无论你尝试什么,你都无法通过。由于这个原因,C 标准甚至没有提到,例如 C17 7.21.6.1 §8:floatfloat

f,F
一个论点......double


与您的问题无关,您已经混合了,这里:.常量的类型为 - 给出一个 .floatdoublefloat test=5.5;5.5double5.5ffloat

你应该养成一种习惯,不要在同一个表达式中混合 或整数操作数,因为 C 语言有各种微妙的隐式提升规则。floatdouble

评论

0赞 Clifford 9/29/2023
这是一个错误,还是只是一个烦人的设计决策?毕竟这是一个警告,而不是错误。这并不是说它在语义或句法上不正确。在低端 MCU 上,您可能需要一条警告,指出 32 位类型已提升为 64 位。您可能还需要一种方法来抑制它。在任何情况下,在此类部件上使用任何 FP 都可能是不明智的。
0赞 Lundin 9/29/2023
@Clifford 这是一个非常清晰的错误;这些函数的工作原理自古以来就为人所知,对任何人来说都不足为奇,尤其是对于试图设计编译器的人来说。一直以来都不可能将浮子传递给 ,这就是为什么在古代 C90 中甚至不存在的原因。那些使用浮点和低端 MCU 的人应该得到他们所拥有的东西。printf%lfprintf
0赞 Clifford 9/30/2023
但据我了解,代码可以正确编译和运行。发出警告本身并不是一个错误。当然,这并不是说警告并非毫无意义。
0赞 Lundin 10/1/2023
@Clifford 它并不能完全建立对编译器的信心。显然,错误也没有得到修复。
0赞 Clifford 10/1/2023
在这一点上,我们完全同意,可怕的芯片与古怪的编译器。
0赞 chux - Reinstate Monica 9/30/2023 #2

Normally is for and for , right ?%ffloat%lfdouble

No.


With and friends, and are both for .printf()"%f""%lf"double

"l (ell) ... has no effect on a following a, A, e, E, f, F, g, or G conversion specifier."
C Spec: The fprintf function

float arguments to a function like are first converted to a and it is a that receives....int printf(const char * restrict format, ...);doubledoubleprintf()


With and friends, matches a and matches a .scanf()"%f"float *"%lf"double *


how can I make this warning go away without doing printf("%f\n", (double)test)

  • The warning does not follow the C spec. See if that particular warning can be disabled.

  • Use a compliant compiler.

  • Of course one could change code: make a , don't use , ...testdoubleprintf()