为什么 printf 中 int 到 float 转换失败?

Ste*_*epp 3 c printf type-conversion implicit-conversion conversion-specifier

使用 int 进行 float 隐式转换时,失败并显示 printf()

#include <stdio.h>

int main(int argc, char **argv) {
    float s = 10.0;
    printf("%f %f %f %f\n", s, 0, s, 0); 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用它编译时gcc -g scale.c -o scale会输出垃圾

./scale
10.000000 10.000000 10.000000 -5486124068793688683255936251187209270074392635932332070112001988456197381759672947165175699536362793613284725337872111744958183862744647903224103718245670299614498700710006264535590197791934024641512541262359795191593953928908168990292758500391456212260452596575509589842140073806143686060649302051520512.000000
Run Code Online (Sandbox Code Playgroud)

如果我显式地将整数转换为浮点数,或者使用 a 0.0(这是 a double),它会按设计工作。

#include <stdio.h>

int main(int argc, char **argv) {
    float s = 10.0;
    printf("%f %f %f %f\n", s, 0.0, s, 0.0); 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当用它编译时gcc -g scale.c -o scale确实输出预期的输出

./scale
10.000000 0.000000 10.000000 0.000000
Run Code Online (Sandbox Code Playgroud)

怎么了 ?

gcc (Debian 10.2.1-6) 10.2.1 20210110如果这很重要的话我正在使用。

Vla*_*cow 6

转换说明符f需要一个 类型的对象double。通常sizeof( double )等于8whilesizeof( int )等于4。此外,整数和双精度数具有不同的内部表示形式。

使用不正确的转换说明符会导致未定义的行为。

来自 C 标准(7.21.6.1 fprintf 函数)

9 如果转换规范无效,则行为未定义。275)如果任何参数不是相应转换规范的正确类型,则行为未定义。

至于类型的对象float,由于默认参数提升,它们会转换为类型double

来自 C 标准(6.5.2.2 函数调用)

6 如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并且具有 float 类型的参数将提升为 double。这些称为默认参数促销

所以这些电话printf

printf("%f %f %f %f\n", s, 0.0, s, 0.0); 
Run Code Online (Sandbox Code Playgroud)

printf("%f %f %f %f\n", s, 0.0f, s, 0.0f); 
Run Code Online (Sandbox Code Playgroud)

相对于结果是等价的。

请注意,某些输出双精度数的程序员l在转换规范中使用长度修饰符,例如%lf。然而,长度修饰符没有任何作用,应该被删除。

  • 在你的回答中,你写道:“但是长度修饰符没有效果,应该被删除。”——我不同意你的说法,即它“应该”被删除。例如,程序员可能更喜欢使用“%lf”而不是“%f”作为“double”的原因之一是它适用于“scanf”和“printf”。因此,我认为写“可以”而不是“应该”会更合适。 (2认同)