4 ms·
That's not because of C, that's because of GCC.
by hashmal 9y ago
That's not because of C, that's because of GCC.
- adrianratnapala 9y agoIt's because of C as it has been redefined in recent times, but the kinds of people who write standards and compilers. The galling thing is that they did this to win a benchmark war against Fortran.
- int_19h 9y agogcc does it precisely because the C standard says that it can do so, and any program that's relying on not getting broken that way is not valid C (well, "undefined behavior", but it's the same thing in practice).
- pkolaczk 9y agoWhere exactly does C standard explicitly say it can do so? UB was introduced to allow skipping checks that otherwise might have added overhead, like array bound checks or null checks or to give more flexibility to how correct programs are optimized (e.g. freedom to evaluate arguments in any order). Therefore each compiler/library/os vendor could implement these cases differently. However, it was never meant to allow compiler to assume "ok, I can see your code is totally broken, so let's break it more, cause you don't care anyway".
- steveklabnik 9y agohttp://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf is the draft of the C11 spec, 3.4.3 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). ------------- Even if you want to argue over what "imposes no requirements" means, I'd argue that "ignoring the situation completely with unpredictable results" is very clear. The note also says (and elsewhere in the standard it reinforces this) that since there are no requirements, implementations could absolutely do things like perform runtime checks, etc. Compilers do not do this though. This isn't for no reason, but that's a separate issue.
- loup-vaillant 9y ago> However, it was never meant to allow compiler to assume "ok, I can see your code is totally broken, so let's break it more, cause you don't care anyway". That's nevertheless how compiler writers are interpreting the standard right now. Take integer overflow for instance. Stuff like this: unsigned u = some_computation(); int x = u; // because of reasons x += 42; // hmm this may overflow, let's check that if (x < 0) { // It's a 2's complement machine, this'll work handle_overflow(x); // now, let's deal with the overflow } Now here's how your optimising compiler see that stuff: unsigned u = some_computation(); int x = u; // x is always positive. x += 42; // signed integer never overflow if (x < 0) { // x was positive, no overflow... always false handle_overflow(x); // Let's delete this dead code. } Then, what actually happens: unsigned u = some_computation(); int x = u; x += 42; This is insane.
- deleted 9y ago[deleted]
- smitherfield 9y agoA correction: a compiler would not be able to assume that `x` is always positive because casts between signed and unsigned integer types are based on their binary representation (what computers see), not their value (what humans see).[1] [1] https://wandbox.org/permlink/dDDAJjOlm50GD1PW https://wandbox.org/permlink/dDDAJjOlm50GD1PW It would be able to (correctly) make that assumption if `x` were a long, assuming 64-bit longs and 32-bit int/unsigneds.
- int_19h 9y agoIn the C standard, a cast from unsigned to signed integer is undefined behavior if it overflows. So the compiler can, indeed, assume that "x" is always positive in the code snippet above - if the value of "u" is such that it would require signed wraparound when initializing "x", the rest of the program is U.B., and so that possibility doesn't even have to be considered.
- smitherfield 9y ago
- reacweb 9y agoBefore the standard, C compilers applied a principle of least surprise. The standardisation has created a huge mess by leaving so many undefined behaviours were compilers could do as they want.
- userbinator 9y agogcc does it precisely because the C standard says that it can do so Or rather, because the standard "imposes no requirements". A compiler that does the obvious/sensible thing for UB can also claim conformance. From C99 3.4.3 paragraph 3 (emphasis mine): "Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message)."