C was not created as an abstract machine
Ok, so this article is at least contributing to the good side of the discourse about undefined behavior, because it isn&#x27;t actually delusional about reality. (I mean this in the sense of people being deluded&#x2F;having the wrong notions about actual facts, by the way, rather than actual craziness. The people who are deluded about undefined behavior tend to say things like &quot;C is definitely a portable assembler&quot; or &quot;compilers are trying to trick me&quot; which are definitely false. A non-deluded person can be <i>upset</i> about the current state but understanding how C currently works is important if you want to discuss it.)<p>Anyways, to the actual content of the article, I agree with it but I think the frustration it accepts as reasonable is actually misguided. Here is my understanding of how things ended up for C (disclaimer: I was not born when most of this stuff happened.)<p>In the beginning, you had a C compiler for your computer, and it was basically just an assembler. This is what the &quot;make C great again&quot; people think the language really is under the hood, by the way. However, very quickly people realized that they want their C code to run elsewhere, and every computer does things differently, so they needed to have some sort of standard of what was approximately the lowest common denominator for most machines and that become the C standard for what it is legal to do. The guarantee created at that point was that if you conform to the standard, every implementation of C has to run your program as the standard specifies. This was palatable to people because they had a bunch of machines with weird byte orderings or whatever, and it was obvious what would happen if the dumb compilers of the time translated their platform-specific code to a new architecture.<p>Later, the weird architectures started becoming rare. At the same time, though, a new architecture started growing: a virtual architecture, one where the compiler would actually &quot;port&quot; your code to the exactly same processor you were compiling for before, but the code would run faster. It would do this by starting to take latitude through intermediate transformations which it assumed it could do because your program should have been portable to the abstract machine.<p>Now, this completely weirded people out, because &quot;I&#x27;m compiling to a new virtual architecture called &#x27;x86-64 -O3&#x27; that is the same as &#x27;x86-64 -O0&#x27; but faster and more restrictive&quot; sounds really stupid. It&#x27;s the same architecture, and they&#x27;re not even real processors! But if you really think about it compilers are really just taking advantage of the fact that your code is portable, because it works in the space of the C abstract machine, to do a &quot;port&quot; called &quot;run a bunch of optimization passes&quot;. People understand when a port ends up causing a trap on another processor because of course it does that on the new platform. But getting people to understand that your unaligned accesses on the &quot;-O0&quot; machine are no longer valid on the &quot;-O3&quot; machine, because, again, the instructions that come out look awfully similar and straightforward most of the time, except for the weird times where a change &quot;surprises&quot; you because the transition between the two crossed through an invalid space. Kind of like a path that seems to have a &quot;weird jump&quot; because it normally crosses through 3D space and at some point someone found a shortcut through the fourth dimension.<p>Anyways, the performance virtual architecture is all well and good, but what I think will be interesting moving forward is the <i>security</i> virtual architecture, where overflows and out-of-bounds accesses and type confusions are focused on more. Right now as a side effect of performance optimization they end up causing headaches for people, but Valgrind&#x2F;sanitizers are an interesting look into what compiling to &quot;x86-64 for security testing&quot; architecture looks like. The logical next step is even more exciting, because we&#x27;re actually starting to deploy <i>real</i> architectures with security-focused features that will require ports that are every bit as concrete as any other physical architecture difference, which I think will &quot;legitimize&quot; this mindset to the people who I called deluded at the start of this now very rambly comment. Page protections means that &quot;const&quot; is not something you can ignore. Pointer signing can mean that your &quot;but they&#x27;re the same bits underneath!&quot; type confusions are no longer valid. ARM&#x27;s Morello now means you can&#x27;t play fast-and-loose with your pointers anymore; they&#x27;re 128+ bits and you can&#x27;t just decide you want forge one out of an integer anymore without caring. Ports to these architectures absolutely rely on the existence of a C abstract machine, which has served pretty well considering that its existence is really just what a piece of paper says is legal or not, rather than something really planned beforehand.