4 ms·
I think you are confusing undefined behaviour with implementation-defined behaviour. The compiler is within its rights to optimise your program under the assum
by denotational 5y ago
I think you are confusing undefined behaviour with implementation-defined behaviour.
The compiler is within its rights to optimise your program under the assumption that undefined behaviour is never invoked; this holds irrespective of the particular libc implementation you happen to be using.
You cannot assume that the specific libc implementation makes it "safe" to invoke UB in general.
As far as I'm aware, the specific example you give (signed integer overflow) has nothing to do with the libc implementation; it doesn't even have anything to do with the underlying architecture, since the compiler is still allowed to optimise under the assumption it never happens, even if it has well defined semantics on an x86.
On the other hand it's perfectly valid to rely on implementation-defined behaviour, assuming you can determine the implementation, but signed integer overflow doesn't fall into this category.
- hedora 5y agoI'm reasonably sure signed integer overflow is implementation defined to mean twos complement overflow on x86. Of course, assuming two's complement is non-portable, and the compiler is free to add a flag that breaks or enforces my assumption. It's much better to add some casts (that the compiler will compile away on most architectures). However, that doesn't solve the problem of legacy code that assumes it is on an x86.
- denotational 5y ago> I'm reasonably sure signed integer overflow is implementation defined to mean twos complement overflow on x86. I think you're mistaken, or are using implementation-defined in a colloquial sense; the term implementation-defined has a specific technical meaning in the context of C that isn't the same as how it might be used in common parlance. The distinction between implemention-defined behaviour and undefined behaviour is extremely important, because as soon as you invoke the latter your program "doesn't exist" and a standards-conforming compiler is allowed to do whatever it wants. Signed integer overflow is explicitly given as an example of UB by the C standard [1], in 3.4.3: > 3 EXAMPLE An example of undefined behavior is the behavior on integer overflow. By my reading, the specific part of the standard that makes signed overflow UB is in 6.5: > 5 If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined. This is completely unrelated to what actually happens when you issue an ADD instruction on an x86; the C standard doesn't care about this. [1] : http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
- MereInterest 5y agoImplementation-defined means that an implementation must choose a behavior, document that behavior, and then consistently apply that behavior. Undefined behavior means that an implementation need not have consistent behavior, need not issue any warnings, need not be predictable, need not be repeatable. The classic example is that if you have signed integer overflow, the compiler is allowed to make demons fly out of your nose, and the C Standard would see nothing incorrect about that behavior. It doesn't matter that the compiler's output is x86. You are entirely correct that x86 has signed integer overflow, but you aren't writing x86 assembly that runs on an x86 processor. You're writing C code, and that runs on the C Abstract Machine. The compiler's job is to output x86 code that will produce the same output as the C Abstract Machine outputs. If the C Abstract Machine doesn't define a behavior, then that means any x86 is acceptable by the Standard.