bmandale 5 days ago

These are all such nonsensical misinterpretations of what people mean when they say C is "low level". You absolutely don't write C for the C abstract machine, because the C spec says nothing about performance, whereas performance is one of the primary reasons people write C.

The existence of undefined behaviour isn't proof that there is a C "virtual machine" that code is being run on. Undefined behaviour is a relaxation of requirements on the compiler. The C abstract machine doesn't not have signed overflow, rather it allows the compiler to do what it likes when signed overflow is encountered. This is originally a concession to portability, since the common saying is not that C is close to assembly, but rather that it is "portable" assembler. It is kept around because it benefits performance, which is again one of the primary reasons people write C.

2
pornel 5 days ago

I'm not trying to prove a novel concept, just explain how the C spec thinks about C:

> The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

This belief that C targets the hardware directly makes C devs frustrated that UB seems like an intentional trap added by compilers that refuse to "just" do what the target CPU does.

The reality is that front-end/back-end split in compilers gave us the machine from the C spec as its own optimization target with its own semantics.

Before C got formalised in this form, it wasn't very portable beyond PDP. C was too opinionated and bloated for 8-bit computers. It wouldn't assume 8-bit bytes (because PDP-11 didn't have them), but it did assume linear memory (even though most 16-bit CPUs didn't have it). All those "checking wetness of water... wet" checks in ./configure used to have a purpose!

Originally C didn't count as an assembly any more than asm.js does today. C was too abstract to let programmers choose addressing modes and use flags back when these mattered (e.g. you could mark a variable as `register`, but not specifically as an A register on 68K). C was too high level for tricks like self-modifying code (pretty standard practice where performance mattered until I-cache and OoO killed it).

C is now a portable assembly more because CPUs that didn't fit C's model have died out (VLIW) or remained non-standard specialized targets (SIMT).

pjmlp 5 days ago

C performance exists thanks to UB, and the value optimising compilers extract out of it, during the 8 and 16 bit home computers days any average Assembly developer could write better code than C compiler were able to spit out.

codr7 5 days ago

And also because it doesn't get in your way of doing exactly what you want to do.

OCASMv2 5 days ago

If that was true then the optimizers wouldn't need to exist in the first place.

codr7 5 days ago

Compared to the alternatives.

It gets very frustrating to communicate at this level.

pjmlp 5 days ago

The alternatives outside Bell Labs were just as capable.

OCASMv2 5 days ago

I don't think compilers allowing trash through is a good thing.

codr7 4 days ago

That's an opinion, another one would be that the flexibility allowed by undefined behavior is one of C's strengths at the same time. Strength/weakness are often two sides of the same coin. Which is why these discussions get a bit circular.

greenavocado 4 days ago

Have you ever seen the error steamroller? https://github.com/mattdiamond/fuckitjs

dwattttt 4 days ago

ON ERROR RESUME NEXT rears its ugly head again