> As I said up-thread, it's possible to define a C dialect without UB, it's just not what most of its users actually want out of the language, since on current hardware it adds significant runtime overhead.
So my core point is this: It's not UB that enables this optimization. When you ask "how can that optimization be legal without UB?", the hard part is "without UB" all by itself. If you have a language with UB, the optimization is easy to enable. If you have a language without UB, the optimization is easy to enable. That optimization is not an example of why we need UB.
> Isn't QEMU both the machine and the compiler (EDIT: perhaps better-put, what's the distinction? They're both just the implementation.) The bytes only need to be unchanged on read from inside the program; if you compile them to something else, that's fine. Prolog programs can introspect with clause/2 and it doesn't cause trouble there.
Basically, I don't think "The bytes only need to be unchanged on read from inside the program" is true. If you're compiling machine code you're not in charge of the entire computer. The code might ask other code to look at the bytes, and you won't be able to intercept that unless you do some kind of ridiculous rootkit takeover when the compiled program launches, creating a virtual machine and moving everything that was already running into it.
I believe simply disallowing "+" and "-" from accepting pointer types is slighlty less work than writing logic for "integral + pointer", "pointer + integral", "pointer - integral", and "pointer - pointer". Although on the other hand it means that instead of literally rewriting "a[i]" to "*(a+i)" in the AST, one has to write a separate logic for array accesses so... okay, so it's exactly as easy to compile ("as hard" technically works as well, but since it's actually rather easy, not hard, I've chosen "as easy", hope you don't mind).
Yep, that's one approach, though that's just as hard to compile as one that is defined to trap and end execution on an out-of-bounds write.
As I said up-thread, it's possible to define a C dialect without UB, it's just not what most of its users actually want out of the language, since on current hardware it adds significant runtime overhead.
> The machine [...] the compiler
Isn't QEMU both the machine and the compiler (EDIT: perhaps better-put, what's the distinction? They're both just the implementation.) The bytes only need to be unchanged on read from inside the program; if you compile them to something else, that's fine. Prolog programs can introspect with clause/2 and it doesn't cause trouble there.