17 ms·
Learn C programming and the rest will come
- alew1 9y agoMeh. Learn any language and “the rest will come” if you then learn other languages. Some of these points don’t lead to C’s being a better first language or pedagogical language — like, why should a learner care that C is so fast? I teach HS computer science and we do use C, in our Data Structures course, after students have used Racket, Python, and Go. Using those other languages lets us cover interesting and important topics like recursion, data abstraction, concurrency, and more, all while doing projects that hold kids’ attention (sometimes using outside libraries for image or sound processing, e.g.). C is well-suited to the data structures course where students have to think carefully about memory and efficiency. I can certainly imagine a different sequence, where students learn logic gates, hardware, assembly, then C, working their way up to higher levels of abstraction. Even in this case though, the goal isn’t to jump in and start writing big programs in C right away.
- maxxxxx 9y agoI think people should understand pointers, heap vs. stack and other things. even in higher level languages a lot of performance problems can easily be explained if you understand how memory works. I often see people allocating and copying huge arrays back and forth and then thinking they need bigger machines.
- cloudster314 9y agoI agree that people should understand pointers, heap and stack. However, there's going to be drop outs from the class if these things are focused on too early. Of course, this is open to debate, which is why we have this type of healthy discussion. You might be right in your assumption that it's better to introduce these concepts earlier. In know that when I was in high school, these concepts were taught and served as a foundation for further learning. It's out of vogue now to teach these concepts to kids. But, you might be right. I need to think about this more. Thank you for your posts.
- agoodthrowaway 9y agoDropouts are ok and honestly a good thing. Not everyone is cut out to be an engineer. I think the commenter is correct. C makes you learn how a computer works. As your code gets more sophisticated you'll eventually have to know this or you can't take your work to the next level. I don't know C all that well and I'm currently facing gaps in my knowledge that would be filled in had I spent some time with a C compiler.
- maxxxxx 9y ago"Dropouts are ok and honestly a good thing. Not everyone is cut out to be an engineer." Agreed. Unfortunately the job market pushes people into professions they are not suited for. I bet 90% of lawyers do it for the career prospects and not because they like law.
- ralmidani 9y agoThat's like saying everyone should be introduced to Math via integration rather than counting because not everyone is cut out to be a Mathematician. I accept your premise that we don't want to push people into professions they are not capable of doing well in. But basic knowledge of programming is becoming important enough that I think providing a gentle intro is wise. Like Math and Physics, you can ramp up the difficulty in later classes.
- pjmlp 9y agoI learned all those concepts in Pascal, BASIC and Z80, about 4 years before seeing C for the first time. C isn't the only language with such features.
- mcguire 9y agoAnyone seen Pascal, BASIC, or Z80s in the wild recently?
- pjmlp 9y agoPascal: https://www.freepascal.org/ https://www.freepascal.org/ https://www.embarcadero.com/products/delphi https://www.embarcadero.com/products/delphi https://shop.mikroe.com/compilers?programming-language*=pascal https://shop.mikroe.com/compilers?programming-language*=pasc... Basic: https://www.visualstudio.com/vs/universal-windows-platform/ https://www.visualstudio.com/vs/universal-windows-platform/ http://gambas.sourceforge.net/en/main.html http://gambas.sourceforge.net/en/main.html https://shop.mikroe.com/compilers?programming-language*=basic https://shop.mikroe.com/compilers?programming-language*=basi... Z80: Any Assembly will do, pick ARM, RISC-V, AVR, PIC, ....
- maxxxxx 9y agoGood. What other languages are still being used that teach these concepts?
- deleted 9y ago[deleted]
- alew1 9y agoAgreed! It's a question of how you introduce them to these ideas. One option is to start at the bottom (hardware) and go up, so that pointers feel like a welcome abstraction when students encounter them in C. (They will already be used to thinking about memory addresses in assembly.) The other option, and the one I choose, is to go from high-level languages down. What I'm not so sure about is just throwing people in in the middle, so that they are trying to grasp abstractions like functions and variables at the same time as they are trying to understand pointer arithmetic. In the subset of Racket we use, all values are immutable, so an understanding of memory (stack vs. heap) is less necessary. We do still talk about "frames" to understand lexical scope, though, and students get used to thinking of each function call using up a new "frame" of memory to store its local variables. This allows them to understand the memory efficiency of recursive functions. We then move onto Python, and _do_ talk about an "environment" (stack) and a "heap" (I call the heap "object-land" because objects live there). This enables us to talk about garbage collection. More importantly, students get used to thinking about variables as being bound to either primitives or pointers to shared memory. In Go, there _are_ pointers, and students get used to thinking about memory addresses as values. They learn that pointers are useful both for sharing mutable references, and for avoiding expensive copies. (In Go, arrays are values, and passing a large array to a function copies it.) But none of the sharp edges of C's pointers are present. Go does "escape analysis" so that if you return a pointer to a local variable, that local variable is allocated on the heap; it is safe to point to anything and if you do, it won't be garbage collected. There's no pointer arithmetic. By the time they see C, in the third-year course, a lot of the pieces are in place to have a good understanding of how the stack and heap (and manual memory allocation) really work. And along the way, because they were using higher-level languages, the students have been creating cross-platform, complex programs (web servers, games, etc.) that they're proud of. :-) Re: sibling's comment that "some people aren't cut out to be engineers," I think that's a somewhat dangerous attitude. I think the study of computation is profound & rewarding and should be part of a liberal arts education for everyone; even apart from that, programming is also a useful skill for people who won't get a job as an engineer.
- maxxxxx 9y ago"Re: sibling's comment that "some people aren't cut out to be engineers," I think that's a somewhat dangerous attitude. I think the study of computation is profound & rewarding and should be part of a liberal arts education for everyone; even apart from that, programming is also a useful skill for people who won't get a job as an engineer. " Agreed that some basic skills are a good thing. But in the same sense that I have some grasp of writing but never will be a good writer or enjoy it, a lot of people are just not cut out to be software engineers. It would be a sad world if everybody had the same talents.
- cloudster314 9y agoThank you for posting this reply as I agree with many of your points. Also, I didn't know about Racket, which looks like a good tool for teaching. I would like to learn more about how you use Racket. Many years ago, my high school taught fortran first and then assembly as the AP course. This was later changed to Pascal. I believe that assembly was used for some of the same reasons the author is suggesting C. However, I also think that learning Python and Go is a better starting point. Learning about pointers is going to cause a significant portion of the class to drop out or tune out. At some, they will need to learn more about memory addresses, but I think that it can come later when performance becomes more of a concern.
- alew1 9y agoFor our first semester, we use a modified version of "How to Design Programs": http://www.ccs.neu.edu/home/matthias/HtDP2e/ http://www.ccs.neu.edu/home/matthias/HtDP2e/ Highly recommended for teaching! I do teach pointers, but in stages — so that students can understand the mutability behavior of Python lists and other objects, we talk about how a Python list variable, for instance, is _really_ storing a memory address of a list. When we move to Go, they actually use pointers, but unlike C's, it's hard to shoot yourself in the foot with Go's pointers. When we finally get to C, pointers seem natural.
- moron4hire 9y agoI whole-heartedly agree. A lot of C-purists will say things like, "you can't understand programming until you understand pointers". I think it's the other way around. I think one will have quite a difficult time trying to understand how pointers work if your very first language is C where their usage is so prominent and in many cases arbitrary due to a systemic aversion to copying data for no other reason than micro-optimization.
- fapjacks 9y agoMy first language was C, back in the early 90s -- from nothing but the K&R book -- and I did learn pointers before I learned my next language (like truly grok them, have the ability to visualize the concept viscerally). When people in interviews ask me to tell them about the most technically challenging thing I've ever done, I tell them about learning pointers in C as a teenager. Taking everything in its context, nothing else in technology has gone that far in pushing my intellect.
- moron4hire 9y agoI agree, it's extremely difficult to go from zero to "understands pointers". I think it's a hurdle that a lot of people have failed to clear and have quit programming to go into other, less-lucrative fields. I don't think it has to be that way, and I don't think there is any virtue in it, either.
- nurettin 9y agoI was a C64 kid. Basic had peek/poke to read/write memory addresses directly. I still remember 53280 and 53281 as bytes to flip to change screen colors. So it came to me naturally when I saw assembler and Pascal pointers later on. It just depends on how you grew up.
- JoeAltmaier 9y agoIf you don't understand when you're working on a mutable version of a data structure vs a copy, you can't get very far. So at least that part of 'understanding pointers' is crucial in any language?
- maxxxxx 9y agoI agree that learning C gives you a great foundation to understanding a computer. I notice that a lot of people who have only learned languages like Java or JavaScript often have a fundamental lack of understanding of what's going on under the hood. Some assembly would be helpful too.
- monocasa 9y agoMy SO decided to go to a web dev bootcamp a few years back. Before they went, I taught them 6502 asm so that they'd have some idea of how a computer works under the hood. It seems to have helped, and they were clearly the top of their class. Albeit it's hard to separate the effects of that from simply living with someone who can talk with you at the end of each day of class. If I were to go through it again, I'd do it with an MSP430 instead. The 6502's lack of registers that are the same width as the address bus (and therefore the multiple steps of indirection required for full pointers) obfuscated some of the concepts I was trying to convey.
- megaman22 9y agoThe best class I ever took was a computer architecture course where we built up an 8-bit minicomputer from individual gates onward in a logic simulator. It was based on the Tanenbaum Structured Computer Organization and the Patt and Patel "Introduction to Computing Systems* books. By the end we were programming it in a limited dialect of assembly and also with a minimal version of C that compiled down to that assembly dialect. Very cool, and I've never been mystified by pointers since then.
- monaghanboy 9y agoI almost think a better post would be "Learn Computer Architecture and the rest will come". For that, I can't recommend http://nand2tetris.org/ http://nand2tetris.org/ enough.
- 0xfeba 9y ago> With C code, there’s no going into a program without fully knowing what it’s going to do at every step of the way... This guy seems to be putting C on a pedestal. It's OK, for certain jobs. Like kernels, CLI utilities, C/C++ for games, etc. But even there Rust and Go and other tools are invading that space and doing well. When I want to make something, I usually use whatever I think can get me to something usable fast. C is rarely the answer. I think the same holds for someone trying to learn programming. Python or Go removes a lot of cruft that new programmers shouldn't have to deal with, at first. They are good intros to "you want X? Well import X, then start using X.foo" instead of "You want X, well first let's start a Makefile so we can get our libs linked in properly depending on if this is debug or release, and then maybe CMake so we can use it on other systems, and so on and so forth..."
- flavio81 9y ago>What’s so good about it? Well.. C is fast. Agreed! I also agree that K&R "The C Programming Language" is a classic book that everybody should read, at least to admire how well written is it. And of course C is a good language to learn. Not as a "first language" but as one of the "languages to know". >Also, C is flexible. You can do more with C than you can do with newer languages. What?! Yes, you can do anything with it, only if your time doesn't cost. The same is true of Assembly code. There are many languages that are more expressive and powerful than C, and some of them aren't really that slow.
- runevault 9y ago-- And of course C is a good language to learn. Not as a "first language" but as one of the "languages to know". This is how I feel about it. Better to learn with something a bit more forgiving (IMO something like Python is good, even if these days I prefer compiled languages), but as a 2nd, 3rd, or 4th language C or at LEAST C++ should be required. Having to actually deal with memory yourself makes such a huge difference in how you treat your programs.
- orwin 9y agoI disagree. Some of my friend and me were able to implement by ourselves RB tree algorithms by the 18th day of our month-long formation, and only one of us knew how to write code before this (and we almost reached his level the day before, when we implemented linked list algorithms in C). After this formation, we were able to write a hashmap algorithm that handled collision in less than a day and a half. I honestly don't think we would have been able to do the same if the tools we were given during our formation were python, php or javascript. I don't think resolving the philosopher dinner problem in Go can teach you much. In C, it does. The biggest advantage C have is that you start from nothing, so you have to understand everything. I would not understand BTrees this well if i did not first understand linked list. And i think the thing that taught me the most about OOP was writing a raytracer in C.
- flavio81 9y ago>if the tools we were given during our formation were python, php or javascript. Well, these are not the "modern" tools I had in mind with writing my comment above... >I don't think resolving the philosopher dinner problem in Go can teach you much. In C, it does. Yes, I agree. But I never questioned C's value as a teaching aid.
- Philipp__ 9y agoBigger question for me was when does one truly learn C? Finishing C course on college didn't felt like I learned C. Nor implementing some common algorithms and data structures. [Lets mark my experience until this moment as `phase 1`] This attitude made me stay in C for a bit longer, getting my self interested in systems programming and that is when I got to see truly what programming and debugging C really is. I was learning and experimenting for 2 years with that, and I felt recently like I was ready to move on, (Python and Clojure taking over for the most part) and the conclusion was rather strange: Everything after phase 1 didn't brought me that much, considering cost/benefit factor I was not impressed by the end results. While whole first few years and college in C were significant and I recommend it to everyone to learn C even up to a point where you write basic CRUD program that read some data from txt/bin and create linked list with that data and represent it, my venture into systems and lower level programming didn't bring me as much of "general" knowledge. Sure it was good, and I learned C++, and combining those two now I do some other things that are related to the things I learned during that period (like GPGPU), it wasn't that mindblowing as I expected initially.
- danaliv 9y agoI will never understand this trope of "pointers are hard to understand." Yes, they can get you in trouble if used without care. But hard to understand? What's so hard to understand about an address?
- pjmlp 9y agoI learned pointers via Z80 Assembly, BASIC Peek and Poke, Turbo Pascal, as a young kid. Is it so hard to draw a couple of box diagrams to convey the image of pointer and actual memory contents? Maybe we need to get back these kind of books, http://www.atariarchives.org/ http://www.atariarchives.org/
- camus2 9y ago> I will never understand this trope of "pointers are hard to understand." Yes, they can get you in trouble if used without care. But hard to understand? What's so hard to understand about an address? I don't think anybody ever said that pointers are hard to understand, they aren't. Go is a proof of this as even people coming from Python or Javascript can easily pick pointers up even if they have never heard about the heap and the stack before.
- ashark 9y agoThere are posters in this very discussion claiming that pointers were remarkably difficult to learn. I'm firmly in the "WTF is the big deal?" crowd. Every time I see posts like that I think, "maybe I've thought I understood pointers just fine, and even used them without issue, for years and years, but somehow I actually don't understand them?" I had a harder time with OO when I first encountered it than pointers, because I kept running into terrible "Sally wants to buy some lemonade from Tommy"-type introductions in crappy, cheap '90s C++/Java programming books and bouncing off it.
- khedoros1 9y ago> I had a harder time with OO when I first encountered it than pointers Pointers weren't too hard to learn (although, the deeper they're nested, the harder they are to think about, for me). OO felt immediately intuitive, using the "shape class, rectangle class, square class" examples. Recursion is the concept that I understood the general idea of, but had to do immense amounts of work to be able to visualize. I think that everyone has their own areas that they learn easily, that others have a hard time with.
- jokoon 9y agoAgree with it, but it's an unpopular opinion. I often advocate python as a first language, but when you discover that python uses references most of the time, it can get confusing. Ideally, you would teach the basics of assembly, learn the basics of a compiler, and go forward.
- monaghanboy 9y agoI agree with the last statement. I think it's best to learn basic computer architecture before learning C, which assumes a close relationship. I took http://nand2tetris.org/ http://nand2tetris.org/ before learning C; starting from a single logic gate, you build memory, CPU, assembler, and a compiler for small language (you implement malloc and free yourself). [0] Though some folks say it sacrifices depth for breadth, I feel very comfortable learning C now. [0] HN thread for part 2 of the course: https://news.ycombinator.com/item?id=14526344 https://news.ycombinator.com/item?id=14526344 [1] HN thread for part 1 of the course: https://news.ycombinator.com/item?id=13209452 https://news.ycombinator.com/item?id=13209452
- djstein 9y agoI will state that the article itself was a fluff piece. However by posting the title it will bring interesting discussion on hn. I do agree with the title, very much so. I think the Java then C then whatever else you fancy is the best way to start programmers/software engineers out. Put them in a structured environment (strong typing, little room for catastrophic errors), then learn why the structure is there with C, then let them free roam to Python/JavaScript/Rust/Go with the experiences gained by the planning at the C level
- H1Supreme 9y ago> I think the Java then C then whatever else you fancy is the best way to start programmers/software engineers out. I agree. Managing memory, pointers, and potentially problematic compiling should come after you know how to loop over an array (or list, or whatever). Java or C# are two great places to start.
- uiuiuxuxux 9y agoI think learning java first would be very very detrimental to someone's coding skills. They would spend the rest of their careers trying to deprogram themselves from that useless way of structurng problems. For me the best would be first c, then assembly, then lisp. In my experience people That started with java and then learned python or js or something else tend to write horrible convoluted code.
- orwin 9y agoI don't think anyone should go with a language that allow him to do bad OOP. In my experience, this lead to poor code in the beginning, even when this person is one of the most brilliant you ever met. People that learned with C (Pascal too) piss more straightforward code on average, and have better debugging skills. And they are more "aware" of the computer. PS: I did go C, assembly (had to rewrite some libc functions) then emacs lisp (before trying to write stuff in Common Lisp). I don't think going assembly will help a webdev much (even if he work mostly on backend), but lisp is definitly helpfull for anyone. Assembly is great if you like having some fun, but beside CTF and "that one time" (i had a really nasty C bug), the stuff i learned while writing assembly were not really usefull to me.
- nayuki 9y agoI largely disagree with this article. C has too many pitfalls that a beginner can either be discouraged by a non-working program, or not understanding the subtle gotchas. Avoiding undefined behavior in C is difficult, even for experts. Failing to understand UB leads to very inconsistent, often latent, hard-to-debug situations long after the bug has occurred. Other languages - including assembly language - don't have this extremely hostile concept of UB. C encourages bad habits like ignoring error codes from I/O functions. Also, doing concurrency correctly in C (or Java for that matter) is a grand effort, but is easier in languages like Go and Rust. Managing language minutiae in C, like function prototypes and header files, is something not found in newer languages. Another problem is having a global namespace instead of a more structured, modularized one (C++, Java, Python, etc.). And finally, manual memory management means that a lot of extra code is written (contrary to the author's claims about conciseness), and it especially makes string processing hard. Personally, I only use C to implement cryptographic primitives (ciphers and hash functions) and some numerical kernels. These are straightforward calculations that don't require memory management or tricky pointer arithmetic.
- ramzyo 9y ago> C has too many pitfalls that a beginner can either be discouraged by a non-working program, or not understanding the subtle gotchas. Totally agree with you - personally C would have been a very difficult first language for me. Java and Ruby were tough enough at the outset when I started down the programming path. Now I work primarily in C and have been doing so for the last four years or so. Still get hung up on subtle gotchas, especially when interfacing with hardware!
- ayae 9y agoI don't think most of these pitfalls are very problematic for a beginner trying to play with the machine and to understand how things work. > doing concurrency correctly in C (or Java for that matter) is a grand effort And that makes it a great teaching tool for exploring how concurrency works, and what issues arise because of concurrency, in a way that other languages don't expose. It's definitely not easy, but understanding how to use (manual) locking/reference counting/memory barriers can be pretty fun (and I'm not saying it's relevant to every developer). > contrary to the author's claims about conciseness C is a conscise language in the sense that the language itself (its specification) is quite small. The code you write with it can be quite verbose.
- jononor 9y agoMost should choose a more pleasant and productive language, so that the road to make something working and interesting is not uneccesarily long. Starting with C increases the chances of getting stuck and never getting a good feeling about programming - which is sorely needed to stick to it.
- yotamoron 9y agoC for s/w eng is like classic ballet for dancing.
- jventura 9y agoIn my opinion, and assuming the author is talking about learning C as first language, my answer is that it depends. It depends on what you're trying to do with what you're learning, and what you will do after. Basically, if you're studying to be an electronics engineer, I say that C is a good first language to learn the constraints of electronic devices. But if you're studying to be a mechanical engineer, I guess you want to learn programming to solve "data" problems (equations, graphical plots, etc). For the latter ones, something like Python with packages like numpy, matplotlib, etc., is probably more adequate. In a nutshell, I think of learning C first as the bottom-up approach, and learning something like Python the top-down approach. Choosing one or another depends on how down or up you want to go..
- djmetzle 9y agoI agree. With C, you are in control of everything your program does. That means you're also _responsible_ for everything your program does. C requires a very different mindset than dynamic languages.
- howard941 9y agoAs one who's working to get to a productive place with functional programming I disagree: Decades of embedded c preceded by asm hasn't helped out at all.
- srcmap 9y agoFor me, C programming is kind of like Calculus, Physics to modern day Engineering. If you don't know Calculus, Physics, you can be a very good construction workers but hard to know the fundamental behind why/how the Buildings, Cars, Airplanes, are designed that ways. Same for C, if you don't know C. You can certainly a very good program Python, java script, web developers, but might not have deep understand of Kernel, Browser, Database, Network, nor why Java, Go and Rust need all those new language features. Know how the tools are different will help you to choose the best tool for the jobs.
- currymj 9y agoi could not disagree with this more, holy cow. C has so many weird and painful quirks, and is missing a lot of things that a novice programmer will need to know (like object-orientation, especially). it's a great second or third programming language to learn though.
- orwin 9y agoFrom what a saw, exceptionnal people aside, those who learned to code with a language favorising bad OOP (most OOP languages, maybe with the exception of Lisp) write nasty code. Especially when they work with a language like javascript, but even with c++ or Rust you can easely find abominations. Everybody should learn proper data structure before learning OOP. I don't like Go, but i'd much rather work with an intern who was first taught Go than any OOP language, even one i like. OOP is a great tool, but people that learned with it have the tendancy to use it poorly and everywhere, and to use abstractions of abstraction when this is not needed. Maybe for you, it was not an issue, because you were brilliant enough, but for average devs like myself, it is.
- khedoros1 9y agoMy first two languages didn't include object orientation (QBASIC, and badly-taught "C++" that was essentially C with iostreams). From experience, OOP's an easy paradigm to learn later. Early on, you're learning functions, loops, variables, breaking problems into pieces, how to hold a useful amount of the program in your mind at once, etc. BASIC would've been better with better explanation of how some of the keywords worked with memory segmentation. The "C++" would've been better if they actually stuck with teaching us plain C.
- flukus 9y ago> C has so many weird and painful quirks, and is missing a lot of things that a novice programmer will need to know (like object-orientation, especially). I don't think you can understand OO properly without C or another sufficiently low level language. You might learn the concepts at a high level, but it's still important to know at a low level, you know to know about the vtable of function pointers that makes inheritance possible, otherwise you will never truly grasp OO. Also, I'd prefer most devs learn to write functions that operate on data long before they learn how to combine them into a horrible mess.
- GFischer 9y agoCounter-anecdata: My stepfather tried to introduce me to programming via C as a kid (with the very same Kernighan & Ritchie book), and it didn't help at all. An environment with a better REPL and which can do more "fun" programs is better to start out. Motivation to build fun stuff is important - I ended up starting my learning on GWBASIC of all things :) and there were some cool BASIC games. I absolutely agree that C is very important to learn when formalizing a programming education.
- ralmidani 9y agoHaving learned Python, then C++, then JavaScript, then C, then Java, I have to say Java is probably at the sweet spot; it strikes a good balance between providing enough conveniences over C and C++ to help avoid frustrating a programmer (garbage collection, no need to use pointers explicitly) without encouraging total carelessness like Python and JS do (inadvertently) with their lack of built-in static typing. With that said, if you want to provide instant gratification and therefore encourage a beginning programmer to keep learning, Python and JS may be the best for introductory classes. MIT's approach of using Python to do a one-semester survey of CS and Data Science, then using Java to teach serious Software Engineering, appears to be an effective compromise (I did three of their CS courses on edX).