Ask HN: How do I learn C and C++ when I love high-level languages?

53 points by zuck9 ↗ HN
I've been developing using languages like Python, Java and the like with automatic memory management for the past few years. The way I learned these languages was - read their language definition from learnxinyminutes.com, think of personal projects I wanted to make/port, google the API and done.

C/C++ is different, I'm afraid of pointers. I can't think of anything that I will like to make in C/C++ since it is so low-level. What I can do in one line in Ruby will take dozens.

I will really appreciate any pointers on how do I learn them. (no pun intended)

61 comments

[ 3.2 ms ] story [ 120 ms ] thread
Build some system utilities. If you are on Linux/OSX try to program a subset of the features of one of your favorite command line tools.
Find a slow part of your Python/Ruby/Lua application that could use some speeding up and then write an extension for it in C.

Some useful reading:

http://www.swig.org/

http://dan.iel.fm/posts/python-c-extensions/

https://blog.jcoglan.com/2012/07/29/your-first-ruby-native-e...

I agree with @hackerboos, definitely write a c-extension. It will not only enhance your knowledge of python but you will also learn C/C++ during the development. I did something similar wrote a ruby c-extension https://github.com/chaitanyav/fibonacci for fun. Also, checkout the CS107 videos on youtube which are C based (look for cs107 stanford).

you can also try writing the core utils using your newly learned C/C++ skills.(https://github.com/chaitanyav/cprograms)

Agree with hackerboos, but don't use Swig, use the CFFI in PyPy (it has a CPython port). I recommend writing a bloom filter or an off heap data store. Another option is to hack on the Lua VM or Redis, both are excellent C code bases.
C/C++ didn't truly click for me until I had learned assembler. (Helped my understanding of every other language too.)
Assembly didn't really click for me until I learned computer architecture :p

You can always go one level down, but I would hardly say you need assembly for c or c++.

Haha :) True, so I propose adding computer architecture to the things to learn about. Not because I think it is NEEDED but because It was a great benefit in my experience. Just a little goes a long way.
This. Learn Assembly together with C.. it will make C much more clear to understanding.. and then he can go for C++.

For instance, in assembly you push/pop from stack, or you move things into the registers and from memory, you will have to deal with memory address, etc..

So he will learn the most important background about thinking in C, like stack vs. memory allocation, and what pointers really are under the hood (the memory address of a thing)

exactly what happened to me
If you need an interesting project to motivate you, you could try to build something with Arduino. It requires purchasing some hardware, of course, but it's cheap enough to play around with.
(comment deleted)
The other answers sound like they're from people who aren't new to the idea of pointers...

Try simple data structures first. Having linked list nodes that actually uses minimal memory (pointer to next node, a data field) is actually pretty exciting. Implement all the operations (get index i, remove index i, etc) because that's where a lot of the insight will come from. Then you can move onto binary search trees and other more complex stuff.

One of the most useful insights I've read was from "Effective C++", which said (paraphrasing) "C++ is a federation / family of languages which work together". Learn the C subset of it first so you're not overwhelmed with available features, and then you can get back to using templates / STL / the other languages later.

I don't think that C/C++ is different, this is exactly how I learned those as well. Be aware though, that C++ and C are very different languages and you should choose one. If you want to do kernel-level stuff or embedded code, C is probably a better choice than C++, whereas if you want to go into gaming or complex desktop applications (think Photoshop), C++ might be the one to choose.

Pointers may be scary but they are just a concept that you need to grasp, like recursion. You first read about it and kind of get it, then you apply it over and over until suddenly you realize that you have developed a true understanding that allows you to build new abstractions on top.

You will hear people telling you to start with C first because C++ is a superset of C, but I always advice against this. Memory management is "manual" in both, but the idioms you apply are very different between the two. Unless you are looking to truly spend years perfecting both, pick one and go with it.

C++ is also very applicable in kernel programming. See: Haiku, Darwin, Windows. I would not write a C kernel now; Linux and *BSD only maintain relative security and dearth of bugs through years of maintenance and rigorous code guidelines. C++ (even as only a thin layer over the C code) can provide ridiculous modularity and safety that C alone cannot—think RAII and parametric allocators. From a software engineering perspective alone, I think C++ is the win.

C is much better as glue code between languages than anything else.

(comment deleted)
I would usually think of myself as a high-level langauge developer. I've recently been working my way through http://buildyourownlisp.com/ - Which I'm seriously enjoying.

It's doing a great job of teaching me C, while also reminding me how great high level languages actually are!

I'd say just find a good tutorial type book. I got an adequate understanding of pointers from reading C++ for Dummies. Anyway, don't be afraid. Pointers require care to avoid various issues, but they're fundamentally a simple concept. You'll be fine.
Have you tried Go? Might make the transition a little easier. UDP hole punching is always fun with C/C++.
Yes, I did. Absolutely HATE the syntax. Not gonna use it anytime soon.
You don't necessarily have to do low level stuff with C/C++. Sure you'll still be dealing with pointers etc, but my point is it doesn't have to be very low level just because it's C/C++. Depending on what you want to implement it might be a good idea to use a framework such as Qt. http://qt-project.org/
Take a job where you'll have access to senior C++ programmers who'll mentor you. One good way to do this is to get a frontend/webdev job at a company that also does some hardcore C++ backend development, then once you're in the company, offer to start fixing bugs in the core product as long as you get some mentoring/code reviews for them. Most devs don't turn down an offer to help.

You really want to work with people who have done C++ before, because there are a number of tricks (RAII, ownership conventions, using const references and references to signal ownership conventions, smart pointers, unique_ptr, etc.) that are common industry practice but aren't all that well-documented on the web. C++ differs from Java or Python in that often the hard part isn't figuring out how to do something, but figuring out what not to do.

I think you just need an incentive. Try to work on problem where performance really matters such as physics engine or scientific simulator if you are not into OS stuff. You will learn to hate automatic memory management soon enough ;)
Go to a code practice site like hackerrank or oj.leetcode (personal favorite but I suggest using an external compiler for it) and solve problems. Start from the simplest ones and make your way up. Once you solve a problem, go back the following day or week and without using a reference solve it from scratch. After solving a problem look at the solutions provided in the forums. A lot of the time they will be a lot more elegant and contain things you haven't considered or seen before.

This is only half of it. The second half is to choose a mid size project, write yourself something that resembles a spec, and code it up from scratch. It could be some sys util or perhaps a video game (this will require you to learn library linking).

The third half is to read online articles and tutorials while you do the two things above.

The fourth and final half is to get yourself a book once you have a grasp on the language(s) and learn some of their more complicated idioms and pitfalls.

Also as a side note, at this point in time I don't think the "C/C++" conglomerate make much sense any more as modern C++ looks very different from C. Unless you explicitly need C, I would suggest learning C++ first as it's higher level (and also much larger). Though, idk, maybe learning C first is better as it's the foundation for C++... I guess either is fine, just not both simultaneously.

four halves, huh?
What can I say, C++ isn't easy to learn :)
Telling us what type of personal projects you liked doing in the past would be very helpful.

Pick something fun to write (to you) that is normally written in a lower level language.

For me C and C++ were fun to learn by writing graphics applications (ray tracers are great for this) and physics simulations (a solar system simulation maybe). Optimizing these to be as fast as possible is a great way to learn about pointers and manual memory management.

Get yourself an Arduino or some other similar cheap hardware dev kit and build some project for fun? It's a start.
That's what I was going to say - you can really appreciate when pointers are useful if you manipulate registers or memory-mapped I/O.
I think to learn C/C++ it's helpful to have a mindset of wanting to understand the machine rather than build code. It's of course great fun to use Python's built in maps etc (and C++ has equivalents) but what you can do in C/C++ that you can't in Python is create the raw data structures down to the exact memory locations where they'll be used. One of the ways to learn C++ is make a relatively complex data structure (red-black tree, or bloom filter) and then throw as much data as you can inside it, see when you cross a threshold of memory usage -- then see if you can improve on that.

Having said that, C++ has come a long way, despite what haters say. I program primarily in C++ and very rarely have to use pointers. C++11/14 has excellent features (lambdas, initialization lists etc) which can make programming almost seem like writing a Python or Ruby script.

You may also have some luck with Bjarne's smallish "Tour of C++" book -- http://www.stroustrup.com/Tour.html

Look into more recent language features:

https://stackoverflow.com/questions/3016107/what-is-tagged-s...

http://www.stroustrup.com/C++11FAQ.html

Also, the Boost library is worth a look. C++ is fairly expressive if you wield it properly, and it offers several ways to minimize the pain of memory management. I would hesitate to call C++ "low-level". (C is another story.)

Other than that - C/C++ are used to solve different problems from Python, Ruby, etc. It is a common problem that people used to a particular toolset have difficulty identifying tasks that are suited to other tools. The suggestions to write C extensions or ports of command line tools are good ones - these will give you a taste for where C/C++ shine on a much more gradual learning curve than trying to write device drivers or kernel extensions.

Another example of practical C++ usage: in the past, I've often prototyped algorithms in Python, then rewritten them in C++ once the major bugs are ironed out. YMMV, but I found this to be faster than writing directly in C++.

Do you really need to learn a another language, when you don't like its features? All general-purpose programming languages can solve the same problem.
"All general-purpose programming languages can solve the same problem."

That's not really true, in general. They can all compute the same things. Some problems have constraints beyond "what is computed".

I don't get it. What do you mean?
Performance reasons
That's much of it. Another reason might be "no one has written a XYZ interpreter for the target architecture", which may be due to performance or just obscurity. Another problem constraint might be pedagogical - if the problem you are trying to solve is "show how to do X in language Y" then of course language Z can't be used - though that example could reasonably be dismissed as trivially true. I'm sure we can come up with some more if we try.
Work your way through "A Book on C"? That's how I did it...

Actually, I think the best approach would be to pick a project for which you can construct a believable (by you) reason why it should be in C. Some possible reasons:

1) You need precise control of hardware

2) You're running in an environment where higher level languages are not available

3) You need precise control of latencies

4) You need the absolute maximum possible performance

There are various projects with these requirements of various difficulties. I would say that it might be hard to simultaneously convince yourself that a project needs the maximum possible performance and also that it is tractable for you as a newbie C developer.

A simple kernel module might not be a bad thing, if you can do your development in a VM to recover from the inevitable crashes. The reason for C will be quite clear, but tooling will suffer.

Targeting microcontrollers will be similarly well motivated at a higher degree of awkwardness.

Download a Commodore 64 emulator and learn ROM BASIC. Write a game in it. After that, try learning C again. You'll be infinitely thankful for such high-level constructs as functions and structs. And you'll understand what they do a bit better, probably.

Edit: I'm sorry if this sounds condescending, but I really mean it. Basic is about one step above assembler - you get variables and nice access to some basic IO, but it's much closer to the metal than C. It really doesn't even have functions, you have to do GOSUB/RET yourself. It's also an extremely simple language. But it will give you an idea on how computers work at a basic level. After that you should have a much easier time grokking C.

Why do you want to learn C or C++ if you can't think of something you'd like to use them for? I've written a fair bit of assembler and occasionally still do tiny projects in C or C++, but my language of choice (by far) is the highest level general purpose one I've come across.

IMO you don't need to know either C or asm to be a great programmer. Read a book on operating systems instead and you'll know all you need to about hardware. Add a thorough coverage of algorithms and data structures, and you're in a better position to write effective software than many I've worked with.

Because I don't want to get that feeling when I'm reading some C/C++ and have absolutely no idea what's going on.
Some advice I can offer, be very very careful of the quality of resources you use to learn C and C++. In particular look at the year the book/tutorial/etc. was written and try to get stuff that was written or updated recently. Both languages have been around for many years and evolved quite a bit. Advice about how to use C++ in 1990 is vastly different than how to use it in 2014 with modern C++ versions.

Also read some reviews of the book before you spend any time reading it. The mid 90's were a really bad time for C++ in my opinion since it was kind of a new language and being pushed heavily as the default 'learn computer programming' language (which Java later usurped). This means there are tons of very badly written and confusing resources that do more harm trying to teach C++ than actual good. Stuff like Deitel's C++ How To Program, etc.

For C++ in particular I can recommend:

Thinking in C++ (http://mindview.net/Books/TICPP/ThinkingInCPP2e.html) Although it's getting a little old, I think this is a great resource for someone just picking up the language.

A Tour of C++ (http://www.stroustrup.com/Tour.html) Great small intro to modern C++ programming, by the creator of the language.

+1 on A Tour of C++. ~200 pages that do a fantastic job of introducing the language.