【问题标题】:GCC 8 Invalid Result of Implicit int to float cast [duplicate]GCC 8 对浮点转换的隐式 int 的无效结果 [重复]
【发布时间】:2018-09-27 18:51:44
【问题描述】:

当我意识到 OCaml 将整数除法和乘法存储到相同的优先级时,我正在涉足 OCaml,因此 3*4/53/5*4 不同。不知何故,我错误地记得在 C/C++ 中情况并非如此,除法的优先级高于乘法,但每篇文档都说,就像 OCaml C 和 C++ 一样,为 @ 分配相同的优先级987654323@ 和*

我写了一个简单的程序:

int main(int argc, char** argv){
    printf("%f %f",3*5/4, 3/5*4);
}

当我使用 gcc 8.1.1 编译它时,它打印了 0.0000 0.0000,尽管它强化了我的错误信念,但与记录在案的行为背道而驰。怀疑一些奇怪的编译器问题,我试图简单地打印一个格式化为浮点数的整数:

int main(int argc, char** argv){
        printf("%f",20);
}

结果再次得到 0.00000。这真的让我的大脑很乱。现在是凌晨 2 点,我没有得到答案就无法入睡。

P.S.:我已经用 C 语言编程了很多年,要么我在这里做一些非常愚蠢的事情,要么编译器真的把事情搞砸了。

编辑:正如 cmets 中指出的那样,这是一个愚蠢的错误。在 C/C++ 中,/ 的行为类似于正确除法,如果至少其中一个操作数是浮点数,但当两个操作数都是整数时,它变成整数除法。 printf() 也无法执行任何转换,因为它不知道变量的实际类型。我至少赢得了一张反对票,但这将永久提醒我糟糕的默认语义和松散的打字会在哪里咬人。

【问题讨论】:

  • int 值的操作产生int 值,而不是float。尝试打印20.3.*5/4
  • warning: format '%f' expects argument of type 'double', but argument 2 has type 'int' [-Wformat=]
  • 这里没有“隐式转换”。您正在将可变参数 (...) 参数传递给 printf。您有责任确保参数类型与格式说明符正确匹配。如果你需要演员 - 自己做。 printf 将无法理解这里需要演员表。 printf 本质上将可变参数视为二进制数据。
  • 太尴尬了,但是用 Python 编程一段时间让我完全忘记了/ 将执行整数除法,所以3/5*4 的计算结果为 0,但是 3*5/4 呢?
  • @WeatherVane 是的,但没有5/4,因为乘法和除法具有相同的优先级,并且从左到右关联。所以它实际上是15/4,诚然,它给出了与3*(5/4)相同的答案

标签: c


【解决方案1】:

简短的回答是:

在所有情况下,您都将int 传递给printf,但您使用了%f,因此需要一个浮点数。传递与格式说明符不匹配的类型的值(即%f)是未定义的行为。

试试:

int main(void) {
   printf("%f",20.0);  // Notice the .0 
   return 0;
}

顺便说一句:

如果你打开了编译器警告——例如gcc -Wall -Wextra --pedantic prog.c——你会被告知如下:

warning: format '%f' expects argument of type 'double', but argument 2 has type 'int' [-Wformat=]
     printf("%f",20);

这实际上告诉您问题所在。所以建议是...始终将您的编译器设置为最高警告级别并认真对待所有警告。

【讨论】:

  • @farhanhubble 甚至 MSVC 都会对此发出警告,所以我猜 GCC 也会这样做。
  • @WeatherVane 默认不是。
  • @farhanhubble 所以提高警告级别并将所有警告视为错误。
猜你喜欢
  • 2018-07-09
  • 2014-05-09
  • 1970-01-01
  • 2011-03-24
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
相关资源
最近更新 更多