3 ms·
One valuable property of C that the author didn't hit, C code is easily translatable into assembler in your head. He kind of misses this point with the virtual
by joshe 8y ago
One valuable property of C that the author didn't hit, C code is easily translatable into assembler in your head. He kind of misses this point with the virtual machine discussion. Yes C code becomes different types of assembly by platform, but you can look at C and have a clear idea of what the assembly will look like.
This is at a really good level for driving intuitions about what the computer is actually doing. Your concern 99% of the time when you are trying to think at this level is performance, and thinking in C will give you the right intuition about how many instructions your code is generating, what and when memory is being allocated, and which exact bytes are being pulled off the disk for certain function calls.
Modern swift/java/javascript compilers are so good that they will often generate better code than you write. This often makes knowing C a less useful skill. But, even so, when trying to understand what a compiler optimization is doing, you are probably thinking in terms of the C code it is generating. It's at exactly the right level to be clear about what is actually happening without drowning yourself in JUMP statements.
- gambler 8y agoThere is an article about this. 'C Is Not a Low-level Language'. https://queue.acm.org/detail.cfm?id=3212479 https://queue.acm.org/detail.cfm?id=3212479
- saghul 8y ago> One valuable property of C that the author didn't hit, C code is easily translatable into assembler in your head. He kind of misses this point with the virtual machine discussion. Yes C code becomes different types of assembly by platform, but you can look at C and have a clear idea of what the assembly will look like. I've seen this many times, I'll be honest: I can write C, but for the life of me I don't have the slightest clue how the assembly code will look like.
- inetknght 8y ago> I can write C, but for the life of me I don't have the slightest clue how the assembly code will look like. Compiler Explorer can help a ton. https://gcc.godbolt.org/ https://gcc.godbolt.org/ I recommend liberal use of Compiler Explorer to verify claims during code review.
- JonathonW 8y agoSame here. At one point, I probably could've looked at C and had a pretty clear idea of what the 68HC12 assembly would look like... but I've never bothered to learn x86/x64 assembly, or ARM assembly, and I've written way more C code for those architectures than I ever did for microcontrollers back in undergrad.
- Koshkin 8y agoWhy not simply imagine it as something like this: ; c = a + b load reg1, a load reg2, b add reg1, reg2 store reg1, c
- freeone3000 8y agoThat's the correct steps, but that doesn't add anything that the original C code doesn't do. On x86, that could be: mov [ebx], eax add [ecx], eax Which is an entirely separate set of operands, instructions, and addressing modes. It's still the same steps, but it's not really telling you anything.
- lima 8y ago> Yes C code becomes different types of assembly by platform, but you can look at C and have a clear idea of what the assembly will look like. Not anymore, with modern optimizing compilers it's hard to reason about -O3 assembly output. https://godbolt.org https://godbolt.org is amazing to play with that
- munificent 8y ago> Your concern 99% of the time when you are trying to think at this level is performance, and thinking in C will give you the right intuition about how many instructions your code is generating I really don't think that's true given modern optimizing compilers. I remember back when C "best practices" were: * Avoid moving code out into separate functions since calls are expensive. * Hoist subexpressions out of loops to avoid recomputing them. * Cache things in memory to avoid recomputing them. But inlining means now we refactor things into small functions and usually expect that to be free. Optimizers automatically hoist common subexpressions out of loops. And caching is useful, but making your data structures larger can cause more data cache misses, which can be more expensive that just recomputing things. I've seen good CPU cache usage make a 50x difference in performance. Even in C, optimizing is now an empirical art and not something you can reason about from first principles and running the compiler in your head.
- TheDong 8y agoIf you want a developer to have a good intuition for what assembly looks like, the only real way to do that is for them to take an assembly class or to play with assembly a bit. It doesn't really matter if the assembly they play with comes from C or Rust or C++ or any other language that outputs assembly. In short, learning C doesn't teach you assembly. Learning assembly teaches you assembly.
- Too 8y agoYou are conflating that it is possible for a human to reasonably fast manually "compile" C into assembly, with that being the only way to do it. Many times the resulting code from modern clang/gcc is so optimized there isn't even any assembly code left to reason about. Even with -Og i many times get the famous "Optimized out" when trying to look at a variable in GDB, with -O3 even more so. You are correct though that it is a close as you are going to get compared to many other languages, mostly because they all will make use of GC, vtables and dynamics on almost every line of code which adds noise in generated output or they run behind an interpretter or JIT.