News for hackers. Stuff that matters.
Re:GCC 6.1 Released by Filligree on Wednesday April 27, 2016 @08:28AM (#11579751)
Oh, hooray. I wonder which programs are going to break because of optimizations this time?
Re:GCC 6.1 Released by treehau5 on Wednesday April 27, 2016 @08:33AM (#11579775)
I think this type of thinking is cynical and unhelpful. We complain that compiler technology is not keeping pace, then when they put in god knows how many hundreds of hours of work improving, we complain when we might have to spend a few to go back through our programs and make sure everything's okay. We want everyone else to do the work for us.
Re:GCC 6.1 Released by jabl on Wednesday April 27, 2016 @09:22AM (#11580139)
Knee-jerk rants aside, there is of course the underlying point that C and C++ have such wide scope for undefined and implementation-defined behavior that no mortal programmer can write a non-trivial C/C++ program that follows the standard to the letter.

Whether it's possible to salvage C/C++ by specifying some safe subset (for some ideas towards this see e.g. Regehr's "safe C" or DJB's "boring C") without sacrificing too much performance remains to be seen. Another option, then, would be to start over from a clean slate, e.g. Rust.

While most likely having less of an impact on the world at large, at least personally I find learning myself Rust more fulfilling than the prospect of fighting political battles in the ISOC committée. YMMV, of course.

tl;dr: The above has all to do with the specification of the C and C++ languages rather than compiler writers attempt to exploit the spec to its fullest potential. So yeah, as long as "compiler goodness" is (marketing-wise at least) determined by SPECcpu scores, it's unfair to blame compiler writers for this mess.

Re:GCC 6.1 Released by necessity on Wednesday April 27, 2016 @10:11AM (#11580566)
If it's undefined behavior according to the standard then it's following the standard.

You know of course there is a trade-off between the possibility of optimization and strict compliance to a standard with zero or very little undefined behavior.

It's wrong to say C is "lost" because of these characteristics. It might not be a good fit for what you want to do, then use whatever you think is best. Just as Rust might be better than C for some cases, the reverse is true for others.

Re:GCC 6.1 Released by jjnoakes on Wednesday April 27, 2016 @09:30AM (#11580219)
This is absolutely not true. I work with many C and C++ programmers, and we ship very large amounts of C and C++ code with a very high adherence to the standards.
Re:GCC 6.1 Released by jcranmer on Wednesday April 27, 2016 @10:40AM (#11580797)
I would assert that virtually every non-trivial C/C++ program (>100KLOC) contains undefined behavior.

Here's a list of undefined behaviors that's almost impossible to get rid of:

* Data race. This is particularly fun for anyone who started doing multithreaded code pre-C11/C++11, since volatile does not let you use code across multiple threads without locking.

* Signed integer overflow. Are you sure that there is absolutely no input to your program that would not cause one of your thousands of signed arithmetic operations to overflow?

* Buffer overflow. This is something like 90% of all security vulnerabilities.

* Uninitialized variables. Note that -Wuninitialized doesn't catch all cases, although this is relatively easy to mitigate with a paranoid style guide.

* Strict aliasing rules. Better yet, if you have any sort of custom memory allocation scheme, you're pretty much guaranteed to break this, since the only way you can access an object with a dynamic type of bytes (signed/unsigned char) is via signed/unsigned char. Functions like memcpy or malloc cannot legally be written in C without breaking this behavior. Also, there is not (to my knowledge) any dynamic checker for violations of this property, unlike the other things in this list.

Your program probably has undefined behavior. You just don't know it yet, and your compiler hasn't figured out how to squeak out a 0.5% speedup from screwing you over because of it yet.

Re:GCC 6.1 Released by jjnoakes on Wednesday April 27, 2016 @01:48PM (#11582712)
> I would assert that virtually every non-trivial C/C++ program

First, citation needed.

Second, the programs I work on would fall outside of your "virtually every".

> [big list of things]

This list doesn't prove anything. There's a similar list in the standards themselves. That's how we know what to avoid.

Oh, and we have an in-house static analysis program that catches all of those. And more.

Our code simply has no undefined behavior. It passes our static analysis program, it passes UBSAN, and no compiler has ever miscompiled our code (unless it was due to a compiler bug).

You can try all you like, but there's no way for you to convince me that our code has undefined behavior. And there are plenty of projects out there similar to ours.

> if you have any sort of custom memory allocation scheme, you're pretty much guaranteed to break this

Not true. You should learn about the aliasing rules before you speak authoritatively about them.

> Functions like memcpy or malloc cannot legally be written in C without breaking this behavior

Also not true.

> Your program probably has undefined behavior.

The chances of that are much less than the chances of you not knowing what you are talking about.

Re:GCC 6.1 Released by dzdt on Wednesday April 27, 2016 @04:13PM (#11584116)
Sibling post gave a case study as a citation providing evidence of the assertion: http://blog.regehr.org/archives/1292

In that case (sqlite) code that passed UBSan, ASan, valgrind, and compiled correctly on all current compilers was studied. A new dynamic undefined behavior checker found additional UB defects at a rate over 1 per thousand lines of code.

I would believe your codebase could have a defect rate one, maybe even two orders of magnitude lower. But short of a formal code-correctness proof, better than that seems unlikely.

Re:GCC 6.1 Released by jcranmer on Wednesday April 27, 2016 @04:42PM (#11584355)
It is nothing short of sheer hubris to believe that you have avoided all undefined behavior, particularly given that there exist undefined behaviors that have no extant static or dynamic checkers (hi, strict aliasing).

I do know the strict aliasing rules quite well. As I said in a cousin post, the set of permissible accesses to a lvalue are governed by the dynamic type of an object. As a consequence, strict aliasing queries are not symmetric, which is to say, P* could point to an object of type Q* but not vice versa. The case where this will come up is with signed/unsigned char. If you have a char foo[]; as the dynamic object, it is positively illegal to access that with anything other than unsigned or signed char. This is what really screws up a lot of code.

Re:GCC 6.1 Released by jjnoakes on Wednesday April 27, 2016 @05:01PM (#11584522)
Strict aliasing violations are quite simple for a static analysis program to find and report.

> I do know the strict aliasing rules quite well.

Not well enough, if you think what you wrote above ("memcpy or malloc cannot legally be written in C without breaking this behavior") is true.

Re:GCC 6.1 Released by astrange on Thursday April 28, 2016 @04:16AM (#11587211)
> Functions like memcpy or malloc cannot legally be written in C without breaking this behavior

> Also not true.

You cannot implement malloc in C because malloc always returns a pointer that's not a part of an existing allocation. The malloc in libc has special dispensation from the compiler to do this (GCC "malloc" attribute).

Similarly you can't implement pthread mutexes in C because they imply optimization barriers (all global memory might change) that a C function with a visible implementation wouldn't have.

Re:GCC 6.1 Released by dsfuoi on Thursday April 28, 2016 @04:38AM (#11587292)
You can easily implement malloc. I don't understand what relevance with this your paragraph has.

C11 has atomics and all the necessary primitives, fences, locking, etc..., to implement pthread_mutex, including its own mutex.

Re:GCC 6.1 Released by corysama on Wednesday April 27, 2016 @11:31AM (#11581289)
Strict aliasing is the only item on your list that I could see leading someone to get upset with the optimizer. And, maaaaaaybe signed integer overflow. With strict aliasing, I don't think your examples are correct. They all involve typecasting pointers, but don't involve interacting with the original type later. So, memcpy uses a void* as char* and MyAllocator uses char* as MyType*, but in both cases they never go back and expect predictible new values in the original types.

The rest are clearly taught in CS100 to be doorways to chaos. In particular, complaining that volatile doesn't get rid of the need for locks is just making noise. Might as well complain that auto doesn't get rid of the need for locks. They are both unrelated to threading.

Re:GCC 6.1 Released by Kristine1975 on Wednesday April 27, 2016 @12:44PM (#11582101)
>And, maaaaaaybe signed integer overflow.

Overflow checking is sometimes done like this (where a is a signed integer):

  if (a + 100 < a) ...
Of course this invokes undefined behavior, and some people get angry when compilers remove the check: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475
Re:GCC 6.1 Released by anttihaapala on Thursday April 28, 2016 @04:46AM (#11587325)
And of course the code is wrong, because the behaviour is undefined - in 64-bit architectures it is very common to use 64-bit registers for `int` even if in memory `sizeof(int) == 4`; thus `int a = INT_MAX;`, `a + 100` could still be greater than `INT_MAX`.
Re:GCC 6.1 Released by netheril96 on Wednesday April 27, 2016 @11:54AM (#11581558)
Two points:

- Data race leads to subtle bugs on all languages and runtimes, including Java and C#. They are just not called undefined behavior in those languages.

- char* and unsigned char* are allowed to alias any pointer. This is one of the exceptions to the strict aliasing rule.

Re:GCC 6.1 Released by lomnakkus on Wednesday April 27, 2016 @01:40PM (#11582626)
> Data race leads to subtle bugs on all languages and runtimes, including Java and C#. They are just not called undefined behavior in those languages.

That's because they aren't. You might get incorrect results or exceptions or whatnot, but NOT Undefined Behavior aka. nose-demons. What can happen in cases of data races is always constrained by the VM model. (Obviously, this is modulo bugs in the actual VM implementation, but that probably goes without saying.)

Re:GCC 6.1 Released by netheril96 on Wednesday April 27, 2016 @08:58PM (#11585888)
In practice, undefined behavior is unpredictable because compiler does optimization with the assumption that you do not have undefined behavior. When you do have them, the optimization won't preserve the "as-if" rule.

The same applies to Java/C# when data race is present. The JIT must be generating optimized codes assuming that no data race occurs, because it is impossible to detect or correct them (at least in current implementation). When you do have data race, the bugs will be as subtle and Schrödinger's as if data race occurs in a C program.

Re:GCC 6.1 Released by the_why_of_y on Thursday April 28, 2016 @01:52PM (#11590676)
Data races in Java/C# races will result in incorrect values (which may be serious if your program is doing anything important and subtle to find, as you say), but they will not ever result in "undefined behavior" in the way ISO C defines the term. Specifically a data race in Java/C# will not cause your program to do out-of-bounds memory accesses or use-after-free or corrupting unrelated objects because other parts of the respective VM specifications prevent such outcomes.

For the details see e.g. http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html...

Re:GCC 6.1 Released by jcranmer on Wednesday April 27, 2016 @04:37PM (#11584316)
There is a very important bit of strict aliasing that your statement misses. Yes, char* and unsigned char* can be used to access any lvalue. However, only signed/unsigned char* can be used to access a signed/unsigned char array. (Strict aliasing is defined via the dynamic type of an object, not which alias pairs are necessarily must-not-alias. Symmetry is not inherent, and in the case of char*, it is indeed not present).
Re:GCC 6.1 Released by netheril96 on Wednesday April 27, 2016 @09:02PM (#11585903)
When you write custom memory allocator, you request memory with `malloc` or `mmap` first. The return value of those functions are raw storage, not objects with dynamic type of character array. Neither is the return value of you custom `allocate`. Strict aliasing rule does not apply.
Re:GCC 6.1 Released by dsfuoi on Wednesday April 27, 2016 @02:03PM (#11582896)
There are other exceptions. Signed or unsigned or a qualified type may alias the corresponding type. A type that includes the type as a member.
Re:GCC 6.1 Released by qwyxzy on Wednesday April 27, 2016 @11:30AM (#11581274)
> Functions like memcpy or malloc cannot legally be written in C without breaking this behavior

Sorry, I don't understand this. Does this mean that these C standard library functions cannot be written in C without breaking the ISO C standard?

Re:GCC 6.1 Released by PeCaN on Wednesday April 27, 2016 @12:17PM (#11581780)
Parent is wrong. char, signed char, unsigned char, and void pointers can all legally alias anything. Those functions can be written in standard ISO C.
Re:GCC 6.1 Released by pdw on Wednesday April 27, 2016 @09:53AM (#11580421)
Can you name an open-source C or C++ project that you believe avoids undefined behavior? Because some people have spend serious time looking without success. E.g. http://blog.regehr.org/archives/1292
Re:GCC 6.1 Released by jjnoakes on Wednesday April 27, 2016 @01:53PM (#11582786)
I don't think many open source projects do, no. Most of them aren't extremely quality-focused, and don't spend the money to develop or purchase some of the static analysis and formal verification tools that help a code base reach the level of quality I'm referring to.

But if I tried hard enough, I'm sure I could find a few that have been run through some sort of formal verification tool.

Whether I could or not doesn't change my assertion at all though.

Re:GCC 6.1 Released by necessity on Wednesday April 27, 2016 @10:21AM (#11580640)
I cannot see the language being at fault in cases such as the ones pointed out by the article:

> SQLite’s vdbe struct has a member called aMem that uses 1-based array indexing. To avoid wasting an element, this array is initialized like this: p->aMem = allocSpace(...); p->aMem--;

Re:GCC 6.1 Released by dzdt on Wednesday April 27, 2016 @10:59AM (#11580962)
In its deep history, the C language was defined by what the implementations did. Only later was it standardized, with an attempt to permit existing implementations be viewed as conforming or easily updated to be. Even decades later, though, the culture of developers tends to the view that something which has always worked in every important implementation should be allowed and continue to work in new implementations. This is such an example. Only a new generation of compiler writers are challenging this, trying to shift to a language-lawyer interpretation of the standards.
Re:GCC 6.1 Released by kps on Wednesday April 27, 2016 @11:47AM (#11581477)

  > the culture of developers tends to the view that something which has
  > always worked in every important implementation should be allowed and
  > continue to work in new implementations
Yes, and X3J11 stated as its first guiding principle,

  > Existing code is important, existing implementations are not.
But then they committed the original sin against “simple C” by inventing ‘volatile’, breaking systems code written when p[0]=x was expected to write to location p. Unlike ‘const’, with which the programmer grants additional license to the compiler, C89 granted the non-‘volatile’ license to the compiler by default. In retrospect, I think C would have been better off retaining do-what-I-wrote as the default, and requiring the programmer to grant the compiler license to do otherwise. C already had the ‘register’ keyword to indicate that a variable should be compiled for speed and need not be literally preserved according to a naïve reading of the code.
Re:GCC 6.1 Released by Someone on Wednesday April 27, 2016 @10:09AM (#11580547)
Very high adherence < follows the standard to the letter.

=> You need stronger arguments to make the "absolutely not true" claim.

Re:GCC 6.1 Released by jjnoakes on Wednesday April 27, 2016 @01:51PM (#11582755)
"Very high adherence" means we pass UBSAN, we pass our in-house static analysis tool, we've never been miscompiled by any compiler (modern, old, bleeding-edge, on multiple platforms) unless it was due to a compiler bug, ...

By all practical definitions, and by any measurable way to declare a codebase free of undefined behavior, ours is.

And I bet others out there are too. There are formal verifiers for C programs that are used in industries. Unless there's a bug in the verifier, the program that it verifies is, by definition, free of undefined behavior.

Just because you, or the open source projects you use, don't code to the standards, or don't have or use the tools that help you do so, doesn't mean there aren't industries out there who can, and do.

Re:GCC 6.1 Released by DannyBee on Wednesday April 27, 2016 @09:43AM (#11580338)
Except, they do that too now, with undefined behavior sanitizer available in both llvm and gcc. Sure, it doesn't catch everything everything, but ...
Re:GCC 6.1 Released by lmm on Wednesday April 27, 2016 @08:38AM (#11579813)
> We complain that compiler technology is not keeping pace

Who was complaining about that?

> when they put in god knows how many hundreds of hours of work improving, we complain when we might have to spend a few to go back through our programs and make sure everything's okay. We want everyone else to do the work for us.

Their whole job is to compile our programs - what else is a compiler good for? I don't know who GCC's users are these days - people who care more about benchmarks than working code? Because that seems to be who they're optimising for. Then again I suppose that's the entirety of C/C++'s market these days.

Re:GCC 6.1 Released by chriswarbo on Wednesday April 27, 2016 @09:45AM (#11580355)
> Their whole job is to compile our programs - what else is a compiler good for? I don't know who GCC's users are these days - people who care more about benchmarks than working code? Because that seems to be who they're optimising for.

If all you want the compiler to do is make a working program, just disable all optimisations.

Re:GCC 6.1 Released by dave2000 on Wednesday April 27, 2016 @08:51AM (#11579885)
Are you saying you have an example of valid c++ code which fails to compile, and that this problem is getting worse, or just that you get unexpected behaviour when write bad code?
Re:GCC 6.1 Released by coldpie on Wednesday April 27, 2016 @09:04AM (#11579988)
Compiler bugs caused by optimizations aren't at all unheard of. We got bit by one recently: https://bugs.winehq.org/show_bug.cgi?id=38653

That said, I agree with treehau5.

Re:GCC 6.1 Released by lmm on Wednesday April 27, 2016 @09:54AM (#11580427)
"Valid" in that the standard absolutely requires that compilers give them some particular meaning, no matter how rules-lawyery the compiler is? No. "Valid" in the sense that the intent is perfectly obvious to any reader? Yes, plenty. "bad"? No, unless you use the standard as your definition of good/bad.
Re:GCC 6.1 Released by lomnakkus on Wednesday April 27, 2016 @01:47PM (#11582699)
> the intent is perfectly obvious to any reader

So compilers need to judge what is "perfectly obvious to any reader", now? And you're willing to deal with the fallout of different compilers having different conceptions of "perfectly obvious"?

That's... an ambitious project.

Maybe your time would be better spent convincing the C++ committee to define some more behavior instead of leaving it undefined.

Re:GCC 6.1 Released by lmm on Wednesday April 27, 2016 @05:42PM (#11584814)
The C++ committee exists to standardise the behaviour that major compilers implement. Trying to get them to define behaviour where there isn't already at least broad support would be putting the cart before the horse.
Re:GCC 6.1 Released by wtetzner on Wednesday April 27, 2016 @11:02AM (#11581002)
If you're not interested in performance, but are interested in working code, then why wouldn't you pick something other than C/C++?
Re:GCC 6.1 Released by Kristine1975 on Wednesday April 27, 2016 @08:31AM (#11579766)
Same procedure as every year: Only programs that don't conform to the C/C++ standard.

Not counting true compiler bugs of course.

Edit: The release notes at https://gcc.gnu.org/gcc-6/changes.html mention three programs that apparently will break:

Value range propagation now assumes that the this pointer of C++ member functions is non-null. This eliminates common null pointer checks but also breaks some non-conforming code-bases (such as Qt-5, Chromium, KDevelop)

Re:GCC 6.1 Released by jordigh on Wednesday April 27, 2016 @09:11AM (#11580042)
Or the D standard, or the Java standard, or the Fortran standard, or the Golang standard...

It is the GNU compiler collection, after all. I'm actually particularly excited about a new release of gdc myself. I've been reading Alexandrescu's excellent The D Programming Language, and I think it may be just the better C++ that I always wanted, ahead of Golang and Rust.

Re:GCC 6.1 Released by lmm on Wednesday April 27, 2016 @11:42AM (#11581413)
GCC has an Ada implementation too - you might (or might not) consider that.
Re:GCC 6.1 Released by Filligree on Wednesday April 27, 2016 @08:36AM (#11579792)
At least with the C standard, it's theoretically possible to learn it. I'd challenge you to find one person in your company who fully understands the C++ standard.
Re:GCC 6.1 Released by easytiger on Wednesday April 27, 2016 @08:52AM (#11579892)
Stroustroup in his book claims he doesn't fully understand it.
Re:GCC 6.1 Released by rleigh on Wednesday April 27, 2016 @09:50AM (#11580401)
Well, this is the language where Turing-complete template metaprogramming was "discovered" as an emergent property of the system!
Re:GCC 6.1 Released by CyberDildonics on Wednesday April 27, 2016 @02:10PM (#11582973)
Giant, complicated, wildly successful.
Re:GCC 6.1 Released by octoploid on Wednesday April 27, 2016 @08:42AM (#11579836)
Well, just use -fsanitize=undefined and it will point out (most of) the isuses for you.
Re:GCC 6.1 Released by Ace17 on Wednesday April 27, 2016 @09:27AM (#11580187)
Provided that your test suite properly trigger the execution of tricky parts, in tricky situations (You do have a test suite, right?)
Re:GCC 6.1 Released by Kristine1975 on Wednesday April 27, 2016 @09:34AM (#11580257)
>You do have a test suite, right?

Of course I do. I call it "customers".

Re:GCC 6.1 Released by Ace17 on Wednesday April 27, 2016 @10:51AM (#11580891)
Ok great then, and don't forget to tell them to compile using "-fsanitize=undefined" !
Re:GCC 6.1 Released by typon on Wednesday April 27, 2016 @10:24AM (#11580659)
We do love our customers don't we? They make the best testers.
Re:GCC 6.1 Released by pjmlp on Wednesday April 27, 2016 @10:47AM (#11580856)
Well, not all C compilers have it.
Re:GCC 6.1 Released by pjmlp on Wednesday April 27, 2016 @09:25AM (#11580171)
And I challenge you to find someone that knows all C rules about UB across all major compilers.
Re:GCC 6.1 Released by octo_t on Wednesday April 27, 2016 @11:51AM (#11581522)
Undefined behaviour is the same across all compilers. The compilers aren't the things which make the behaviour undefined, its the C standard.
Re:GCC 6.1 Released by pjmlp on Wednesday April 27, 2016 @12:32PM (#11581965)
No it is not, if you ever tried to write portable C code you should clearly be aware that each C compiler has its own flavor of undefined behavior.

The C standard is very generous in terms of undefined behavior freedom.

Re:GCC 6.1 Released by dsfuoi on Wednesday April 27, 2016 @03:18PM (#11583653)
By definition made in the C Standard, undefined behavior is: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

If you're using some other definition, then say so, otherwise your comments make no sense.

Re:GCC 6.1 Released by pjmlp on Thursday April 28, 2016 @01:22AM (#11586697)
Given my-app.c, each C compiler out there will pick a different UB subset and not everything that is defined as UB in the standard.

They are free to do that and still be compliant, after all UB means anything goes.

Re:GCC 6.1 Released by lorenzhs on Friday April 29, 2016 @09:20AM (#11595494)
That compilers may behave differently is exactly the point of UB, if they all had to behave the same it wouldn't be undefined, after all!
Re:GCC 6.1 Released by hellofunk on Wednesday April 27, 2016 @10:09AM (#11580544)
True dat. C is a smaller language and is possible to know the whole language, but not the whole spectrum of UB. C++ is a vastly larger language it is nearly impossible to know the whole language, but much more likely to understand the spectrum of UB.
Re:GCC 6.1 Released by DannyBee on Wednesday April 27, 2016 @09:42AM (#11580333)
Actually, some: "Type-based alias analysis now disambiguates accesses to different pointers. This improves precision of the alias oracle by about 20-30% on higher-level C++ programs. Programs doing invalid type punning of pointer types may now need -fno-strict-aliasing to work correctly."
Re:GCC 6.1 Released by ben0x539 on Wednesday April 27, 2016 @09:19AM (#11580106)
They're helpfully listed in the release notes!

> This eliminates common null pointer checks but also breaks some non-conforming code-bases (such as Qt-5, Chromium, KDevelop)

Re:GCC 6.1 Released by jbb555 on Wednesday April 27, 2016 @09:23AM (#11580152)
We do seem to have got into a race to make C and C++ compilers less and less useful while still following the letter of the rules (but certainly NOT the spirit).
Re:GCC 6.1 Released by Kristine1975 on Wednesday April 27, 2016 @09:26AM (#11580180)
I think modern C and C++ compilers are very useful. Then again I know that these languages are full of huge pitfalls, so I know what I'm getting into, and when I make a mistake I blame myself, not the compilers.

I also use the features of modern C/C++ compilers such as warnings (-Weverything on clang, then turn off those warnings I'm not interested in) and sanitizers (Undefined Behavior Sanitizer, Address Sanitizer).

Re:GCC 6.1 Released by wtetzner on Wednesday April 27, 2016 @11:08AM (#11581045)
I was under the impression that the whole point of undefined behavior in the spec was to give implementers flexibility. Am I wrong? If not, then it sounds like it's very much in the spirit of the rules.
Re:GCC 6.1 Released by jordigh on Wednesday April 27, 2016 @11:18AM (#11581153)
That's implementation-defined behaviour (do something nonstandard and document it) or unspecified behaviour (do something specific and nonstandard but don't have to document it).

Undefined behaviour allows the compiler writer to have the code do anything unreliable and unpredictable and not document it. Its purpose is to allow compiler writers to completely ignore the erroneous code that results in UB and not spend effort trying to diagnose it or implement it. Most compilers still make an effort to diagnose some UB anyway, though.

Re:GCC 6.1 Released by lmm on Wednesday April 27, 2016 @11:41AM (#11581401)
The original reason was to ensure the standard was compatible with existing compilers (i.e. to leave behaviour which varied between existing compilers unstandardized) and to allow hardware-native behaviour for things like integer overflow and extended shifts, not to allow aggressive optimizations.