【问题标题】:C 's format specifierC 的格式说明符
【发布时间】:2015-09-14 13:23:07
【问题描述】:

我在 C 中有这段代码-

#include <stdio.h>
void main(void)
{
    int a=90;
    float b=4;
    printf("%f",90%4);
}

输出 0.0000,我不明白为什么??? 我知道 90%4 返回 2 并且指定的格式说明符是 %f,这是双精度,但我期望的是 - 它会给出一个错误,但它显示 0.0000 作为输出。 谁能解释一下原因?

【问题讨论】:

  • 为什么你认为它会抛出错误?另外,请始终使用 int main()return 0;
  • 由于类型不匹配,格式说明符为 %f,返回值为 int。
  • 如果它不会显示错误,那么为什么它不显示2.0000
  • 这里无用的ab 有什么意义?你的意思是printf("%f", a % b);?这甚至无法编译,因为 % 只能对整数类型进行操作

标签: c int


【解决方案1】:

90%4 的类型将是int

使用%f 作为int 的格式说明符的行为未定义。

输出可能是 2,也可能是 0。编译器甚至可以吃掉你的猫。

【讨论】:

    【解决方案2】:

    出现这种差异是因为编译器和库没有就类型进行通信。发生的情况是您的 C 编译器观察到 printf 是一个带有任意数量参数的可变参数函数,因此额外的参数会根据它们各自的类型传递。如果幸运的话,它还会解析格式字符串并警告您类型不匹配:

    $ gcc -Wformat -o fmterr fmterr.c
    fmterr.c: In function ‘main’:
    fmterr.c:6:2: warning: format ‘%f’ expects argument of type ‘double’, 
    but argument 2 has type ‘int’ [-Wformat=]
      printf("%f",90%4);
      ^
    

    但这仍然只是一个警告;就编译器而言,您可能已将 printf 替换为具有不同行为的函数。在运行时,浮点和整数参数甚至可能不会放在同一个地方,当然也没有相同的格式,因此不能保证 0.0 的特定结果。真正发生的可能与平台 ABI 有关。您可以通过将 printf 参数更改为 (float)(90%4) 之类的东西来获得指定的行为。

    【讨论】:

      【解决方案3】:

      printf 是一个可变参数函数。这样的功能是晦涩难懂的,没有值得一提的类型安全。这些函数所做的是将小整数类型隐式提升为intfloatdouble,但仅此而已。它不能做更微妙的事情,比如整数到浮点数的转换。

      所以 printf 本身不能告诉你传递了什么,它依赖于程序员来指定正确的类型。诸如90 之类的整数文字属于int 类型。使用 %f 说明符,您告诉 printf 您传递了 double,但实际上传递了 int,因此您调用了未定义的行为。这意味着任何事情都可能发生:不正确的打印、正确的打印、程序崩溃等。

      显式转换 (double)(90%4) 将解决问题。

      【讨论】:

        【解决方案4】:

        %f 需要一个 double,而你在 printf 中传递了 int(90%4=2)。因此,导致 Undefined Behaiour 并且可以输出任何东西。

        你需要显式地强制转换 -

        printf("%f",(double)(90%4));   
        

        不要尝试这样做,因为编译器会产生错误(正如@chux Sir 所指出的那样)-

        printf("%f",90%(double)4);   
        

        【讨论】:

        • 这两个版本不等价,因为第一个版本将对两个双精度执行模计算,如果适用,添加小数,但也可能在结果中添加浮点不准确性。而后一个版本将对整数进行计算。
        • @Lundin printf("%f",90%(double)4); 甚至不是合法的 C 代码。 “二进制 % 的无效操作数(有 'int' 和 'double')”
        • @chux 我没有编译那个。但事实证明它会让人不开心。我会修复它
        • @chux 哦,对了,我忘记了在 % 运算符的特定情况下,C 标准强制执行 int。你必须使用 fmod() 或类似的函数。
        【解决方案5】:

        简而言之:格式说明符没有错误检查。如果您的格式正在寻找双精度,那么您作为参数传递的任何内容(或者即使您什么都不传递)都将被解释为双精度。

        【讨论】:

        • %f 在 printf 中查找 double,而不是 float
        • 不回答问题!
        【解决方案6】:

        默认情况下,90%4 给出一个整数。 如果您使用%f 说明符打印整数,它将打印0。

        例如,printf("%f", 2); 将打印 0。

        你用浮点数对结果进行类型转换,你会得到 2.00000。

        printf("%f",(float) (90%4)); 将打印 2.00000

        希望它澄清。

        【讨论】:

        • printf("%f", 2); 将调用未定义的行为,它可以打印任何内容。查看所有其他答案。
        • 它会打印 0,我敢打赌。
        • 你认为未定义的行为有多未定义?
        • 您对我维护打印 0 的完全符合标准的 C 编译器打赌多少?
        • your 机器上,使用 your 编译器,它会打印 0。因为标准没有定义这种类型的参数不匹配会发生什么,不能保证另一个编译器会生成相同的结果。它可能会,但你不能依赖它。
        猜你喜欢
        • 1970-01-01
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        • 2018-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-19
        相关资源
        最近更新 更多