3 ms·
The basic problem with this assumption is that people who follow it tend to get it in their heads that since C is merely "translat[ing] fairly straightforwardly
by jcranmer 4y ago
The basic problem with this assumption is that people who follow it tend to get it in their heads that since C is merely "translat[ing] fairly straightforwardly to machine code", they assume they can rely on the semantics of the machine code being the semantics of their C program. That isn't true, and hasn't been for a long time [1]: compilers are only required to uphold the looser semantics of C, and they will happily apply optimizations that deviate from the semantics of a purported naive translation to machine code. The usual example brought out to explore this difference is signed integer overflow, which has nothing to do with inlining or loop unrolling.
[1] I don't know enough about the early history of C to be able to assert that it was never true, but it certainly hasn't been true since at least 1989.
- flohofwoe 4y agoI think compiler writers understand this "C is a portable assembler" entirely differently than regular compiler users, because compiler writes are in the trenches all day long and focus (too much?) on relatively minor code generation and memory model details which are just not relevant for most compiler users in their day to day work. Of all the popular high level languages, C is still (among) the closest to CPU and memory, especially when taking compiler specific language extensions into account which are often simply not available in even higher level languages. And while modern compilers do all sorts of funky and sometimes surprising code transformations in their optimizer passes, I can still look at a piece of C code and the compiler's output as assembly, and figure out which parts of the C code result in what parts of the assembly code. Some parts may be massively reduced, some parts expanded (e.g. by loop unrolling), some parts may have disappeared completely or shuffled around, but the relationship is still recognizable. Also, from the POV of a programmer in the 70's or 80's who's used to manually stamping out separate programs for each CPU type in assembly, and then switches to C and only needs to write code once which then runs on different CPUs as if by magic, C would absolutely count as a "portable assembler", and I guess that's the origin of that phrase.