gcc的-Wbad-function-cast的目的是什么?

Cha*_*les 6 gcc warnings compiler-warnings

正如这里的答案所建议的那样,我转过头来-Wbad-function-cast看看我的代码是否有任何gcc可以捕获的不良行为,并且它出现了这个例子:

unsigned long n;
// ...
int crossover = (int)pow(n, .14);
Run Code Online (Sandbox Code Playgroud)

(这不是关键在这里,crossoverint,它可能是unsigned long该消息将是相同的).

这似乎是一个非常普通和有用的演员的例子.为什么这有问题?否则,是否有理由保持此警告开启?

我一般都喜欢设置很多警告,但我无法围绕这个用例.我正在处理的代码是大量的数字,并且很多时候根据需要将事物从一种类型转换为另一种类型以满足所涉及的算法的不同需求.

Kon*_*rov 5

你最好认真对待这个警告.

如果你想从pow的浮点结果得到整数,那就是舍入操作,必须用标准的舍入函数之一来完成round.使用整数转换执行此操作可能会产生意外情况:您通常会丢失小数部分,例如,2.76最终可能会像2整数截断一样2.12结束,就像最终一样2.即使您想要这种行为,也最好使用floor函数明确指定它.这将提高代码的可读性和可支持性.

  • 推荐楼层可能会提高可读性,但实际上并没有帮助.floor()返回一个double,(uint32_t)floor()仍抛出-Wbad-function-cast (9认同)
  • 我们在 C99 及更高版本中有 lrint 和 llrint。这个答案中的下限仅用于确定舍入方向。此外,即使没有任何印记,如果有天花​​板或地板,我们仍然可能会收到警告。但我们不会得到惊喜。 (2认同)
  • 那么,当 `floor` 或 `trunc` 似乎不起作用时,应该如何摆脱警告?而且只有当您直接从返回值(可用于规避警告)进行转换时才会出现此警告-警告的目的是什么?如果通过变量将 `2.76` 输入到 `int` 是不是很糟糕? (2认同)

max*_*zig 2

警告的效用-Wbad-function-cast是有限的。

-Wall既没有也没有启用该警告可能并非巧合-Wextra。它不适用于 C++(仅适用于 C/Objective-C)。

您的具体示例不会利用未定义的行为或实现定义的行为(参见 ISO C11,第 6.3.1.4 节)。因此,此警告给您带来的好处为零。

相反,如果您尝试重写代码以取悦-Wbad-function-cast您,则只需添加多余的函数调用,即使是最新的GCC/Clang 编译器也不会对其进行优化-O3

#include <math.h>
#include <fenv.h>
int f(unsigned n)
{
  int crossover = lrint(floor(pow(n, .14)));
  return crossover;
}
Run Code Online (Sandbox Code Playgroud)

(反面例子,没有发出警告-Wbad-function-cast但有多余的函数调用)