3 ms·
I agree with all your arguments. The function pointer <-> void pointer conversion in particular is an excellent example. But the very last example, unsigned ->
by pascal_cuoq 14y ago
I agree with all your arguments. The function pointer <-> void pointer conversion in particular is an excellent example. But the very last example, unsigned -> signed conversion, is not a good illustration of the point you are making then.
unsigned -> signed conversion is already “implementation-defined behavior” (as opposed to “undefined behavior”). The standard does not guarantee how it behaves but forces compilers to make a choice and to stick to it.
A different example, of a behavior that is really undefined, would be signed arithmetic overflow:
int detect_max(int x)
{
return x+1 < x;
}
The function above branchlessly detects that its argument is INT_MAX, and returns 1 in this case thanks to 2's complement representation.
Except that it doesn't. The command “gcc -O2” compiles it into “return 0;”. GCC can do this, because signed arithmetic overflow is undefined behavior. The compiler is only taking advantage of undefined behavior in a way locally convenient.
Now that two's complement is (almost) everywhere, making it the standard for signed arithmetic overflows is the sort of bold choice I would like to see, but it won't happen (it would break GCC's existing optimization).
- haberman 14y agoGood point about undefined vs. implementation-defined, though even implementation-defined behavior could break programs that switch to a different implementation that makes a different choice.