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.
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 instance2.76
may end up as2
with integer truncation, just as2.12
would end up as2
. Even if you want this behavior, you'd better to specify it explicitly withfloor
function. This will increase readability and supportability of your code.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
:(negative example, no warning emitted with
-Wbad-function-cast
but superfluous function calls)