Most active commenters
  • pjmlp(3)
  • codr7(3)

←back to thread

218 points signa11 | 11 comments | | HN request time: 0.202s | source | bottom
Show context
pjmlp ◴[] No.43681194[source]
> The reason I believe C is and always will be important is that it stands in a class of its own as a mostly portable assembler language, offering similar levels of freedom.

When your computer is a PDP-11, otherwise it is a high level systems language like any other.

replies(7): >>43682173 #>>43682246 #>>43682554 #>>43682928 #>>43683332 #>>43683914 #>>43701871 #
pornel ◴[] No.43682173[source]
Less controversially, when you write C, you write for a virtual machine described by the C spec, not your actual hardware.

Your C optimizer is emulating that VM when performing symbolic execution, and the compiler backend is cross-compiling from it. It's an abstract hardware that doesn't have signed overflow, has a hidden extra bit for every byte of memory that says whether it's initialized or not, etc.

Assembly-level languages let you write your own calling conventions, arrange the stack how you want, and don't make padding bytes in structs cursed.

replies(2): >>43682625 #>>43682918 #
1. bmandale ◴[] No.43682918[source]
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.

replies(2): >>43682955 #>>43689019 #
2. pjmlp ◴[] No.43682955[source]
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.
replies(1): >>43683954 #
3. codr7 ◴[] No.43683954[source]
And also because it doesn't get in your way of doing exactly what you want to do.
replies(1): >>43684796 #
4. OCASMv2 ◴[] No.43684796{3}[source]
If that was true then the optimizers wouldn't need to exist in the first place.
replies(1): >>43685475 #
5. codr7 ◴[] No.43685475{4}[source]
Compared to the alternatives.

It gets very frustrating to communicate at this level.

replies(2): >>43686719 #>>43689366 #
6. OCASMv2 ◴[] No.43686719{5}[source]
I don't think compilers allowing trash through is a good thing.
replies(2): >>43699806 #>>43701396 #
7. pornel ◴[] No.43689019[source]
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).

8. pjmlp ◴[] No.43689366{5}[source]
The alternatives outside Bell Labs were just as capable.
9. codr7 ◴[] No.43699806{6}[source]
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.
10. greenavocado ◴[] No.43701396{6}[source]
Have you ever seen the error steamroller? https://github.com/mattdiamond/fuckitjs
replies(1): >>43702730 #
11. dwattttt ◴[] No.43702730{7}[source]
ON ERROR RESUME NEXT rears its ugly head again