10 ms·
In my quest to learn C very well over the past few years, I've come to the conclusion that C is best understood if you think about it in terms of the way that a
by robertelder 10y ago
In my quest to learn C very well over the past few years, I've come to the conclusion that C is best understood if you think about it in terms of the way that an assembly language programmer would think about doing things. An example of this would be if you consider how switch statements work in C. Switch statements in C don't really compare to switch statements that you find in other languages (eg. https://en.wikipedia.org/wiki/Duff%27s_device https://en.wikipedia.org/wiki/Duff%27s_device).
The issue that many students face in learning low level C, is that they don't learn assembly language programming first anymore, and they come from higher level languages and move down. Instead of visualizing a Von Neumann machine, they know only of syntax, and for them the problem of programming comes down to finding the right magic piece of code online to copy and paste. The idea of stack frames, heaps, registers, pointers are completely foreign to them, even though they are fundamentally simple concepts.
- tyingq 10y ago>I've come to the conclusion that C is best understood if you think about it in terms of the way that an assembly language programmer would think about doing things I agree with this. I found another article that made the transition for someone coming from something like Python or Ruby easier. It shows how to use gdb as a sort of C REPL. https://www.recurse.com/blog/5-learning-c-with-gdb https://www.recurse.com/blog/5-learning-c-with-gdb The quick feedback loop certainly makes things like pointers, arrays, etc, more clear.
- cderwin 10y agoWow. I've been flirting around with learning C for awhile now (coming from a couple dynamic languages, including python), and this is by far the most helpful read about pointers I've ever come across. Thanks a ton.
- startling 10y ago+1 to this. GDB and valgrind are the best things about writing C.
- douche 10y agoValgrind is the best thing since sliced bread - saved me so much time and agony...
- nickpsecurity 10y agoGood idea. Give them these: http://neugierig.org/software/c-repl/ http://neugierig.org/software/c-repl/ https://root.cern.ch/cint https://root.cern.ch/cint
- kachnuv_ocasek 10y agoAlso picoc: https://code.google.com/archive/p/picoc/ https://code.google.com/archive/p/picoc/
- nickpsecurity 10y agoHeck yeah. Thanks for the tip. Btw, new link is here: https://github.com/zsaleeba/picoc https://github.com/zsaleeba/picoc
- Gibbon1 10y agoOne things that I've found enlightening is when you have an IDE that allows you to step through mixed source and assembly. You can see your data being slopped around and processed. (int a = 10; becomes ld R4,10)
- gh02t 10y ago> The issue that many students face in learning low level C, is that they don't learn assembly language programming first anymore, and they come from higher level languages and move down. Instead of visualizing a Von Neumann machine, they know only of syntax, and for them the problem of programming comes down to finding the right magic piece of code online to copy and paste. The idea of stack frames, heaps, registers, pointers are completely foreign to them, even though they are fundamentally simple concepts. What about teaching C in the context of something like AVR programming, where you have to worry about those sort of things because there simply isn't any abstraction on top? That was where I first encountered C and I think learning it in such a constrained environment helped me appreciate/understand the utility of C a lot more.
- deleted 10y ago[deleted]
- pjmlp 10y agoPascal and Basic are also an option when targeting AVR: http://www.mikroe.com/mikropascal/avr/ http://www.mikroe.com/mikropascal/avr/ http://www.mikroe.com/mikrobasic/avr/ http://www.mikroe.com/mikrobasic/avr/
- pcwalton 10y ago> I've come to the conclusion that C is best understood if you think about it in terms of the way that an assembly language programmer would think about doing things. I don't agree. That leads people to incorrect conclusions like "int addition wraps around on overflow" (mentioned in the article), "null pointer dereferences are guaranteed to crash the program", "casting from a float pointer to an int pointer and dereferencing it is OK to do low-level tricks", and so forth. C is a language that implements its own semantics, not the semantics of some particular machine. Confusing these two ideas has led to lots and lots of bugs, many detailed in John's other blog posts. It might be useful to teach these intuitions to beginning programmers who already know assembly language before learning C (though are there more than a vanishingly few number of those anymore?) But teaching assembly language as part of, or as some sort of prerequisite for, teaching C strikes me as a waste of time and likely to lead to wrong assumptions that students will eventually have to unlearn.
- robertelder 10y agoI think you do have a point about possibly misleading people in relation to signed overflow, since that is common hardware behaviour, but for the point about null pointer de-reference, I believe thinking in terms of assembly would actually help people realize that referencing memory location 0 (if that is what null was defined to), will not immediately crash your program. It is not special, it's just another memory location. Your point about teaching assembly as being a waste of time also has some merit. Of course people still do program in assembly, but it is only becoming more and more rare to actually need someone to program assembly, which is why it just isn't emphasized as much any more and it makes C seem like an even stranger language for someone who started on Python or Javascript.
- pcwalton 10y ago> I believe thinking in terms of assembly would actually help people realize that referencing memory location 0 (if that is what null was defined to), will not immediately crash your program. It is not special, it's just another memory location. No, it is special. Dereferencing it is undefined behavior. It is not guaranteed to result in a load at address zero.
- ryao 10y ago> In my quest to learn C very well over the past few years, I've come to the conclusion that C is best understood if you think about it in terms of the way that an assembly language programmer would think about doing things. An explosion ample of this would be if you consider how switch statements work in C. Require students to write a toy operating system and compiler in C. They will understand things obscenely well by the time that they are finished. Another option is to introduce students to DTrace and require them to use it to answer questions about kernel and userspace behavior. Ask the right questions and they will learn all of the things you want them to learn from the process of answering the questions.
- jxy 10y agoIt's wonderful that the article mentions the Duff's device. I still remember the mind-boggling effect when I first met it. It taught me many things. Once you understand it you will never make mistakes with switch/case in C anymore.
- WalterBright 10y agoI took to C like a duck to water, probably because I was just coming from having extensive experience programming the PDP-11 in assembler, and C looks and behaves a lot like 11 assembler. (Such as integral and floating point promotion rules.)
- unimpressive 10y ago>and for them the problem of programming comes down to finding the right magic piece of code online to copy and paste. This seems like a particularly uncharitable thing to say about people who write code in a 'high level' programming language. You're alleging not just that they don't understand the fundamental low level workings of a computer, but that they don't even understand how to write new programs in their language?
- paulddraper 10y agoUncharitable...probably. Though there is some truth to that. It's far more likely that copy-and-paste X is a workable solution in a higher-level language than a lower-level one. A high-level language emphasizes portability and abstraction; a low-level languages emphasizes performance and implementation details. So...the comment sounds harsh but in reality is a reflection of the success of high-languages.
- douche 10y agoC really only clicked for me when I was taking my computer architecture class in college - working through the Patt & Patel book[1], along with the Tanenbaum book[2], and building an entire 8-bit CPU from the gates up in a simulator. I've seen so many people that just can't wrap their heads around pointers, but it makes so much more sense when you've gotten down to the nitty-gritty level and built up from there. [1] http://www.amazon.com/Introduction-Computing-Systems-gates-beyond/dp/0072467509 http://www.amazon.com/Introduction-Computing-Systems-gates-b... [2] http://www.amazon.com/Structured-Computer-Organization-Andrew-Tanenbaum/dp/0131485210/ http://www.amazon.com/Structured-Computer-Organization-Andre...
- plaidturtle 10y agoPersonal anecdote: C was the first language I learned while I was in middle school. I taught myself. I admit that I have gained a deeper understanding of C after I recently took Computer Architecture class, but I don't think learning assembly is essential to understanding the C language, stack/heap, and pointers. When I was first learning C, a simple memory diagram with simple description was sufficient. Perhaps the problem is learning a high level language first (most schools start with python or java)? Maybe students struggle with the transition or it isn't explained well enough. I couldn't say since I started with C. I'm interested if anyone had this problem because I tutor students.
- n0w 10y agoMy experience was similar. I taught myself C during high school, and found transitioning to higher level languages to be fairly simple after that. C was taught as one of the later languages in my university course, and many of my friends (that started with higher level langauges) struggled to pick it up.
- AceJohnny2 10y agoTo add to the others noting the differences between C's behaviour and the underlying assembly, I recommend Chris Lattner's (the creator of LLVM) series of posts about Undefined Behaviour in C: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-... http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-... http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-... (HN truncates the text of the URL, but they're all different) I've been coding C professionally for over a decade, as required for firmware/embedded development, and those posts have instilled the fear of god in me.
- exDM69 10y ago> ... and those posts have instilled the fear of god in me. But why? Yeah, hitting UB can be a terrifying idea but rarely happens in practice. In two decades of C programming, I have hit an UB bug exactly once when a piece of code was ran on an ARM platform for the first time. It took a little bit of staring at disassembly and reading some docs to sort out but it wasn't the end of the world. Understanding the basic cases is a good idea but the darkest corners of undefined behavior are only important if you're a compiler writer like Chris Lattner is.
- jhomedall 10y agoA solid understanding of undefined behavior is required if you want to write software in C that is secure, that will behave properly, and that is portable. Undefined behavior has been the source of numerous security exploits in the past, and will only get worse as modern optimizing compilers become more advanced.
- anexprogrammer 10y agoWhen you want to fully grok C, knowing some assembly and techniques does help. It's irrelevant for those learning the language. They don't need to know about CPU saving effects from fallthrough or lazy evaluation. They're still busy tripping up mixing arrays and pointers and incrementing the wrong one, null pointer assignments or forgetting the break in the switch. When you have some years time and are exploring the edges of the language that knowledge undoubtedly helps. It was rare for students 25 years ago to learn assembly first. Can't say it made it harder to learn or that students had issue (spent a couple of years in the 90s teaching C part time to contractors). They had issue with language beginner things. Pointer arithmetic, or confusing pointers/arrays, but can't ever remember anyone having a particular issue with switch. Fall through was a C thing, they accepted it quite happily, and forgot break sometimes as learners do. People seemed to have far, far more difficulty getting comfortable with C++ and OO than C. The new C++ programmer was much more dangerous than the new C programmer! C was often taught as first "real" language. You'd introduce pointers and here's how that aspect of computers work as part of the same scribble on the whiteboard. Same for memory allocation, stacks, heaps and byte sizes/packing. The fact that C was so directly close to those concepts made grasping them that much easier. We lost a lot when we moved beyond expecting people to be aware of those basics. PHP isn't even sure itself what data is. Being able to pack your data or have app data that's optimal would be appreciated by those "few" smartphone users outside SV where dropping data or fallback to GPRS happens often. Data is rarely thought of in terms of size, it's just a blob of some types/objects. Little surprise when the app spits JSON of epic size and spends half its time "thinking".
- douche 10y ago> Little surprise when the app spits JSON of epic size and spends half its time "thinking" At least it's not XML...