Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: How do I learn C and C++ when I love high-level languages?
53 points by zuck9 on Sept 23, 2014 | hide | past | favorite | 58 comments
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)



First, just to clear things up, C and C++ are two different languages. Yes, C++ is backwards compatible, but you'll do yourself a favor if you start perceiving them as two completely separate laguages now.

Before you start, you need to answer yourself why you're doing it. Unless you really have some inherent interest in the language, learning it just for the sake of learning will be tough because there is no instant gratification.

A good book to start learning C++ is Stanley Lippman's "C++ primer". Make sure you have the latest edition because it reflects the recent big changes in the language.

The best thing you can do when dealing with lower-level languages like C and C++ is understand that things like lists, strings, integers, floating point numbers, objects, etc. do not actually exist. They are simply abstractions. There are only the CPU and memory. You can think of the memory as a very very long array of bytes.Pointers are simply indices for that byte array. Roughly speaking, all that happens in a computer is the CPU fetches some bytes from memory which contain instructions and then modifies the bytes in some other region of the memory according to given instructions.

Once I realized the above things, a lot of other things immediately started making sense to me, so I hope this helps you or others.


Stop being scared of pointers, they aren't magic and you've been using them all along. In most high level languages you are using a pointer for any variable that's not a number. Which is why when you assign one variable to another and modify one it modifies it from the perspective of the other. Because they point to the same object.

Fundamentally, though, they're a value just like any other, just a number that's an index into the giant array called memory. The language provides convenient syntactic sugar to 'dereference' them, which just means evaluate the address and index to it.

Basically:

    *blah
is equivalent to:

    all_of_memory[blah]
which, incidentally, is equivalent to:

    0[blah]
and back around again:

    blah[0]


In all my years, I've never seen anyone describe it like this. Nice one.


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


Good C++ isn't that far from high-level languages. Look at the bullet points here:

http://msdn.microsoft.com/en-us/library/hh279654.aspx

If you primarily use value and reference semantics, RAII, smart pointers, STL containers and algorithms, etc, C++ looks a lot like a really powerful high-level language, because that's what it is. Things only start to get ugly and/or low-level when you are trying to heavily optimize things.

Stroustrop (mentioned in other comments) is a great way to get started, and Effective C++ (http://www.amazon.com/Effective-Specific-Improve-Programs-De...) and its cousins will help you not shoot yourself in the foot.

C is a whole different beast. If you've coded in Java, you have a basic idea of how to do encapsulation in C++. Encapsulation in C is nearly impossible to guarantee. Really, a lot of C programming relies heavily on negotiated conventions and design by contract. Learning the C language is pretty easy (read K&R some weekend), but learning to program well in C is a completely different thing.


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.


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 :)


And on the other hand...


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++.


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.


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.


C/C++ didn't truly click for me until I had learned assembler. (Helped my understanding of every other language too.)


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)


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.


exactly what happened to me


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.


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.


I researched this same question back in 2011. One of the most recommended books is "Memory as a Programming Concept in C and C++":

http://www.amazon.com/Memory-Programming-Concept-Frantisek-F...

A rather expensive book but stellar reviews. I borrowed it from the library. It's very concise too.

For C++ a lot of people still recommend "Accelerated C++":

http://www.amazon.com/Accelerated-C-Practical-Programming-Ex...

because it teaches you "canonical" C++ instead teaching you "C with classes," which seems to be a common complaint among veteran C++ programmers. It's very readable too.

I'm going to pick up "Writing Great Code":

http://www.amazon.com/Write-Great-Code-Understanding-Machine...

because it explains computer architecture. Once you start programming in C/C++ you are much closer to the metal and having an understanding of the architecture will lead to better choices.


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!


Don't be too afraid of pointers - you're already using them if you're using Python when you work with mutable structures.

    >>> a = {'foo': 0}
    >>> b = a
    >>> b['foo'] = 1
    >>> a['foo']
    1
    >>> id(a)
    140428021358832
    >>> id(b)
    140428021358832
`a` and `b` are just pointers to the underlying structure. The only difference is that Python is taking care of the dereferencing for you, whereas in C you would have to explicitly dereference the pointer.

That's all there is to them. It's a reference to another location in memory, which, when dereferenced, refers to that other location. In pseudocode:

    >>> b = 1
    >>> a = &b
    >>> b = 2
    >>> a*
    2
    >>> a* = 3
    >>> b
    3


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.


Take a look at Nim. It is extremely efficient (since it compiles to C) and clean, and will allow you to incredibly easily interface with C or go down to the low level.

http://nim-lang.org/

Also, take a look at DCPU-16 stuff. Assembly might be more fun to play around with. http://www.dcpu-ide.com/ Also x86 assembly. Its exciting because you can get incredible performance and get insight into how things work at the lowest levels. Google x86 assembly tutorial. Also the DCPU-16 has awesome peripherals like the display and even a 3d vector display.

Then when you can come at it from the lowest level pointers are less of a big deal. You can think about making your own OS, (look for a tutorial) and then it will be a more natural progression to C (with pointers).


I can't think of anything that I will like to make in C/C++

Let me address the motivation issue.

C/C++ strength is speed. Write a simple piece of computation in your favorite language (Ruby for instance). Write the same in C and measure the time it takes.

Once you see how slow Ruby is, you may get excited by C enough to continue exploring it.


C/C++ can also produce data structures that are more compact than any managed language could allow. For example, one of the oldest tricks in raytracing is to stuff a few bits of information into the lower bits of a float, so that you don't have to waste a whole byte encoding the metadata for a kd-tree node. But even this is ultimately related to speed. It allows the programmer to squeeze a whole lot into a cache line.


There's also the advantage of sequential memory access, it's generally not idiomatic in higher level languages to use contiguous arrays.


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.


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.


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.


I'd say you just get the book "C Programming: A Modern Approach" by K.N. King. At the end of every chapter there are some exercises & challenges.

It's an excellent book (see the ratings on Amazon) and also fun to read through.

C should be much easier to learn than C++. The language is much more basic feature-wise and the standard C library is very small indeed.

[0]: http://www.amazon.com/Programming-Modern-Approach-2nd-Editio...


I have many timed tried to embark on this very journey and always gave up when I realized I had none of the conveniences available to me as I do with the Java platform.

I thought of all the conveniences of Spring injection, a bazillion java libraries nicely managed by maven etc. The ecosystem available to me in Java is what always made me give up. I guess I never needed to learn C/C++ badly enough to justify the time investment.


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.


You could try doing a cross-platform (iOS/Android) game with a C++ framework like Cocos2d-x. I read through Cocos2d-x By Example (http://www.amazon.com/Cocos2d-X-Example-Beginners-Guide-Enge...) last year and it was pretty good. Didn't assume a prior knowledge of C++


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/


You need to understand how machines work if you want to be a good C/C++ programmer. I suggest Berkeley's CS 61C video lectures: https://www.youtube.com/playlist?list=PL58D76972AD4CB040.


Head First C is an excellent book. It introduces some concepts such as variadic functions and function pointers too early. You might need some supplements on them. I suggest reading through the head first c book and watching youtube videos on topics, you don't quite get at the first time.


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.


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 ;)


Read the part on pointers in the "The C Programming Language" book. Or go to your favorite coffee shop with a C-buddy, buy him some drinks and let him explain ;)


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.


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.


Perhaps use GO or RUST?

Also, I think pascal is great (I use it professionally/Delphi) and the way how pointer and raw code is used is not scary.


(Btw neither Go nor Rust have all-caps names.)


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.


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: