What is the purpose of gcc's -Wbad-function-ca

2019-04-28 03:35发布

As advised by an answer here, I turned on -Wbad-function-cast to see if my code had any bad behavior gcc could catch, and it turned up this example:

unsigned long n;
// ...
int crossover = (int)pow(n, .14);

(it's not critical here that crossover is an int; it could be unsigned long and the message would be the same).

This seems like a pretty ordinary and useful example of a cast. Why is this problematic? Otherwise, is there a reason to keep this warning turned on?

I generally like to set a lot of warnings, but I can't wrap my mind around the use case for this one. The code I'm working on is heavily numerical and there are lots of times that things are cast from one type to another as required to meet the varying needs of the algorithms involved.

2条回答
欢心
2楼-- · 2019-04-28 04:03

You'd better to take this warning seriously.

If you want to get integer from floating-point result of pow, it is rounding operation, which must be done with one of standard rounding functions like round. Doing this with integer cast may yield in surprises: you generally loose the fractional part and for instance 2.76 may end up as 2 with integer truncation, just as 2.12 would end up as 2. Even if you want this behavior, you'd better to specify it explicitly with floor function. This will increase readability and supportability of your code.

查看更多
在下西门庆
3楼-- · 2019-04-28 04:16

The utility of the -Wbad-function-cast warning is limited.

Likely, it is no coincidence that neither -Wall nor -Wextra enable that warning. As well as it is not available for C++ (it is C/Objective-C only).

Your concrete example doesn't exploit undefined behavior nor implementation defined behavior (cf. ISO C11, Section 6.3.1.4). Thus, this warning gives you zero benefits.

In contrast, if you try to rewrite your code to make -Wbad-function-cast happy you just add superfluous function calls that even recent GCC/Clang compilers don't optimize away with -O3:

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

(negative example, no warning emitted with -Wbad-function-cast but superfluous function calls)

查看更多
登录 后发表回答