
Ask HN: I use and love Python. What's the best book to learn C ? - nailer
So it's 2010. I know enough C to be able to read and  patch small apps where I find bugs, but I'd like to sit down and properly learn the language, in a way that encourages neat, usable code for my colleagues, that meets whatever the current standards are for C and covers modern topics like threading. I'm planning on using this to develop Python modules or hack on small Unix tools.<p>I've previously read K and R and found it understandable but a little boring. I really like the Head First series (but alas they have no C book) or anything with lots of examples.<p>What's the best introduction to C book you'd recommend?<p>Edit: Thankyou to everyone who's responded.
======
bensummers
K&R is still the best book on C. Short, simple and accurate.

C++, on the other hand, is a moving target. Difficult to know what to
recommend, apart from suggesting you get something modern which concentrates
on using the STL, and perhaps Boost.

------
tptacek
C Interfaces and Implementations by Hanson. It'll give you back most of the
things you depend on in Python, like variable length strings and dictionaries.

I'm teaching a 4-month weekend C class for Ruby programmers starting in April,
and my syllabus is pretty much built around CII.

~~~
mmelin
That sounds awesome. I wish I was on the right side of the pond.

Have you thought of putting some material online, or even taping the course?
(of course, maybe you don't want to do that for the first iteration)

~~~
tptacek
No, I'm actually pretty skittish about publishing things these days; it's all
risk and no reward. I've been writing C since '94 and I guarantee you there's
some douchebag who will build an entire website about how little I know about
C once the courseware hits Reddit. Pass.

The structure I'm chasing is:

* C Interfaces and Implementations.

* Every month, a couple hours worth of casual exercises, spread over 2 weeks, along with background material and basic courseware (cheat sheets, notes on the book, etc).

* "Tech support" style assistance for those exercises (ie, send me your code and I'll tell you what's wrong).

* Once a month, several hours of lab-style class time. Each class presumes you did the exercises and, if you had trouble, that you chatted me up about them and we got through it. Each class is 2-3 small coding projects. All are security-focused, because that's why we're doing the class; so, for instance, in week 1 we'll probably write an XML fuzzer and a password cracker.

* If you came to class prepared, I'm buying unlimited drinks and pork product at The Publican afterwards.

I'm planning on the following arc for the class:

* Month 1: Basics (Compiling/running, hello-world, malloc and free, the C type system, very basic pointers, using libraries).

* Month 2: Network programming (Stevens-style socket programming, binary formats, I/O).

* Month 3: Design (Library design, voidstar, function pointers, dlopen, object-oriented C).

* Month 4: Secure programming in C (mostly, memory corruption and string handling).

I guess I'm writing all this here not so much to sell a class that I'm not
offering publicly so much as to advocate for the idea of doing things like
this at your own company, and to solicit critiques. I've spent a long time
giving lip service to training and growing a team, and giving up a couple
weekends and plying team members with high-end whiskey seemed like a way of
putting my money where my mouth was. (Also, this is the next thing Erin wanted
me to teach her. So I'm pretty motivated.)

(If you ping me offline, I'm happy to share stuff privately).

------
Kliment
I'd suggest you start dissecting small programs written in C. Those UNIX tools
you were talking about? Grab some UNIX tools, see how they work. Dissect cat,
grep, etc. It's the best way to learn.

~~~
jshen
i don't know that I'd start or even look at grep ;)

~~~
Kliment
It sure ain't pretty, but it does teach you C. The source code is fairly well
documented and does some complex stuff.

~~~
jacquesm
Grep is actually a really good example.

First program your own version of it, then look at the guts of grep and be
amazed at how elegant that solution to the problem is.

And if you come up with the same solution without peeking you will probably be
able to name your own price at some point.

------
pvg
<http://www.c-faq.com/resources/books.html>

Take a look at the Amazon reviews of some of these, you'll probably find
something to your liking.

K&R is an important book to have on your bookshelf but the idea that it's the
only or best book to learn C from is absurd.

Another thing to do is scan the C FAQ and some of the online C tutorials just
to get a feel for the language and where it fits in the language universe and
to understand why a 'modern topic like threading' is not strictly a C topic.
The C coding standard documents of various projects and organizations are also
useful to give you an idea of what peoples' notions of sensible C look like -
they can be surprisingly varied.

Lastly, review known good code in the field you're interested in - in your
case, this might be Python extensions. There aren't a lot of terribly good
reasons to use C to 'hack on small Unix tools'. Your best path to learning the
language is writing things that you actually need and where C is a good (or
only) choice.

------
1331
I highly recommend _C: A Reference Manual_ by Harbinson and Steele. It has
many tiny examples, but it is mainly used as a reference manual (as the title
suggests).

[http://www.amazon.com/Reference-Manual-Samuel-P-
Harbison/dp/...](http://www.amazon.com/Reference-Manual-Samuel-P-
Harbison/dp/013089592X)

A good book for learning C is _Mastering Algorithms with C_ by Loudon. The
source code is over-commented and contains too much white space, which is a
bit annoying, but the content is quite nice.

[http://www.amazon.com/Mastering-Algorithms-C-Kyle-
Loudon/dp/...](http://www.amazon.com/Mastering-Algorithms-C-Kyle-
Loudon/dp/1565924533)

------
kiwidrew
Slightly off-topic, but in case you haven't checked out Cython
(www.cython.org) before, please do! It allows you to write Python code which
is _translated_ into C code that uses the CPython API. This includes classes,
list comprehensions, generator expressions... practically all Python code is
valid Cython code.

I'm honestly never going back to writing C again. Cython gives me all the
expressiveness of Python combined with all the performance and close-to-the-
metal-godlike-powers of C. I've been using it to implement high-performance
graph traversal and routing algorithms and to interface with C/C++ libraries,
and it's been an absolute amazing productivity boost.

However, all of this comes with one caveat: you really need to have a good
knowledge of C to understand Cython and what it's doing. It merely saves you
from the tedium of hand-coding against the CPython API and all of the
boilerplate code that's needed to get much of anything done in C.

------
plinkplonk
First, K&R. Second , C interfaces and Implementations by David Hanson.

------
j_baker
I might get downvoted for this, but I'd recommend going with C++ before you
get into C. You don't have to learn all of the crazy stuff like template
metaprogramming, but C++ does have some tools to make C-like programming
easier. Personally, I'd use C++ _just_ for the string and vector classes.

If you do want to go the C++ route, I hear good things about this book:
[http://www.amazon.com/Accelerated-Practical-Programming-
Exam...](http://www.amazon.com/Accelerated-Practical-Programming-Example-
Depth/dp/020170353X)

Now that I think about it though, if you're still deadset on using C, the
Python source code is actually a pretty easy read. You get two benefits for
the price of one: you learn C and you get to learn more about the internals of
Python. Look here: <http://svn.python.org/view/python/trunk/>

~~~
tptacek
Strong disagree for a bunch of reasons.

First, there's no style of C++ I've seen in the field that totally eliminates
any of the C-isms. Modern C++ code still has pointer math and it still has
function pointers. In other words, you still have to learn the trickiest stuff
from C.

Second, while <vector> is great, it's not a good idea to think about it as a
black box. The whole food chain of STL containers from list to dequeue
presumes that you understand the tradeoffs in actually implementing data
structures in memory. How do you select and use these things intelligently if
you've never even implemented a linked list? You're basically just writing a
very verbose and very error prone form of Java.

Finally, C++ just isn't a very good language. There is _nothing_ you can do in
C++ that you can't deal with in C. There is a clear difference between the
outcomes of, say, Perl and Python --- Python code is clearer and more
maintainable. There are clear differences between Java outcomes and Rails
outcomes --- the Rails code is tighter, smaller, simpler (though perhaps less
featureful). Compare giant C and C++ codebases. What's the C++ win?

C vs. C++ is a can of worms. I know. But I've spent quality time in both
languages and I'm an unabashed fan of C. I think the 2010 answer to the
problem C++ wants to solve is "C and a high-level language". The future
belongs to things like Lua (or Python with a better FFI, or...). C++ is a dead
end.

~~~
DanielBMarkham
This is a great comment but I have to disagree with your conclusion.

I love both C and C++, although I don't use them currently. And I can't
imagine using them in the future.

The issue here: is there a language that is both low-level enough to write
hardware drivers yet high-level enough to abstract away anything that I might
want? Close-enough to the metal to bit flip with the best of them yet powerful
enough to create and organize large hunks of code?

I think the answer is pretty clearly C++. C is a very close second, but the
entire reason from evolving from C to C++ was large development situations.

Would I write a new web-app in C++? Heck no. But software development is a lot
bigger than the little corner of the world I have my fingers in, and I can
easily see where C++ will be around 20 years from now -- and for new
development, not just maintenance. Perhaps even 50 years. So no, not a dead
end by any means.

~~~
tptacek
I use C pretty regularly and I can see why I'd need to keep doing so. If I
have a problem that needs a custom data structure and any degree of
performance, C is how I can keep from wrestling with metadata bloat and
garbage collection.

The problems I tend to solve with C are tightly scoped. They tend to admit to
libraries, where I can get a foo_t from foo_open(), and then pass it to the
foo_bar() functions. They're inherently encapsulated and reusable.

There are things from C++ that I tend to want when I'm writing C. Most
importantly, I want vector, and I want a lookup table that returns results in
sorted order. So, I backported those things from STLPort to C and never looked
back.

There are also things C++ offers me that I think are bad medicine. Classes
with access control (and thus graphs of "friend" relationships): not a win
over ADT-style C libraries. Smart pointers: not a win over pool allocators
(also: knowing how to write a dirt simple allocator is one of _the single
biggest_ performance wins I've seen in my career, and C++ makes that hard).
Templates: not a win over clear, simple code and discrete components.

My experience with C++ is that it creates drag. There are more decision points
in C++ than in C. Do I write a class or do I abstract into a template? Do I
need a special type or is this just a container of primitive types? Do I
decompose into a hierarchy or do I write straight-line code? Do I use a
functor or do I use abstract classes? C is a get-things-done language. C++ is
a talk-about-getting-things-done language. And then code-about-getting-things-
done.

It's OK to downvote me.

~~~
DanielBMarkham
You've made some awesome points, and I don't disagree that C++ has gotten to
the place where you're juggling a freaking lot of stuff around. In straight C
you start at point A and code until you reach point B. In C++ if you're not
careful you create a map of the known world in Portuguese and then start
defining what the word "is" means.

I think back on my C++ production code -- heavy-duty COM stuff, device
drivers, embedded software -- and I'd still stick with C++. The trick is that
I wouldn't pull in every feature from all over the place.

Modern languages -- especially those that have been around for a long time --
have a lot of cruft. Do you need templates on every project? Most likely not.
Do you need the STL? Maybe bits of it but not all by any means. Do you need a
freaking class graph with 50 nodes to start sorting integers? No, but bad
programmers will make one.

One of the reasons I love C++ is that _it makes you understand how to
differentiate the bullshit from the solution_. This is the flip-side of the
exact point you made about having so many options. Got a problem with
allocation? Roll an allocator. C++ is the nuclear bomb of power tools, and
there are a million ways to cut your arm off.

But for small utilities where you don't touch the metal or interact with some
larger, more complex system? C++ isn't the tool.

I completely agree that C++ has some really bad/ouch-don't-do-that things in
there. I just think that overall the pluses outweigh the minuses for a certain
small set of problems. (and coders)

~~~
tptacek
You see C++ as a nuclear weapon. I see it as that automatic hammer Homer
Simpson made after he visited the Edison museum.

~~~
DanielBMarkham
Keeping the topic to "should I learn C++" and "will there be a C++ in the
future"

Want to program the iPhone? Learn Objective-C, a bastardized C++ language

Want to build some shit-hot hardware for NASA or the Defense Department? Pick
up VxWorks and WindRiver -- and welcome to C++

Want to write your own O/S kernal? Hell if I'd do it in C. C++ gives me nice
namespaces and modules and an easier way of organizing things.

So yes, C++ is going to be around for a long, long time. And the concepts you
learn in C++ -- assuming you can become a good C++ programmer -- are going to
make you a much more proficient programmer in any of the "better" languages.

But fair warning: if you dabble? Yes, you'll be Homer Simpson.

~~~
tptacek
No idea why you got downmodded --- perhaps for the crack about OS kernels,
though. Every mainstream OS kernel is C.

~~~
DanielBMarkham
Beats me. I didn't say the existing kernels were C++. I said if I wanted to
write a new one it would be in C++. I certainly know the existing kernels are
C++. Some of the kernel code for popular Operating Systems -- in production
now -- goes back 30 or 40 years.

If I'm not mistaken, the Windows kernel has evolved quite a bit to C++. Even
the core C files are compiled using the C++ switches. Not sure, but not
relevant to my point either.

Hope this discussion helps the poster, which is the goal here. Like I said,
you made some great points, and I agree with quite a bit of what you wrote.
But understanding the exceptions and edge cases are important, even if the guy
doesn't choose C++.

~~~
jacquesm
The reason why you probably would want to write your kernel in C over C++ is
that C++ does more 'under the hood' and when you're writing an OS you want to
have your code as transparent as it can possibly get. Any side effects that
are not explicitly mentioned in the code will get you burned at some point.

------
andrewcooke
not for learning, but as a reference to keep on your desk when programming in
c - harbison + steele <http://www.careferencemanual.com/>

this is also worth reading once you've got the basics down -
[http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp...](http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp/0131774298)

~~~
maw
I second the recommendation of van der Linden's book. It was through that
book, along with lots of programming and experimentation, of course, that I
finally understood C.

------
Maro
A number of people have recommended David R. Hanson's _C Interfaces and
Impementations_ , so I'll mention his _A Retargetable C Compiler: Design and
Implementation_. I own this book though I haven't read it, but it's about
writing a C compiler in C. You should pretty much just go out and buy these
two books because they'll eventually go out of print, and then you'll be
screwed. _CII_ used to be out of print and impossible to obtain until Addison-
Wesley started printing it again a year ago.

~~~
tptacek
You should read it! It's fantastically written, and goes from a hand-written C
lexer all the way to x86 code generation. Hanson's books are written in
literate code style, and it's a shame that that style went out of fashion,
because it is _the answer_ to how to write code-heavy books.

------
nfnaaron
From my C days, I second and third Harbison & Steele. I learned from K&R, but
I learned better from H&S.

From this list (can't say how current they are),

<http://www.c-faq.com/resources/sd19.html>

I liked:

    
    
      - K&R and H&S (if you have to choose, H&S)
      - The Standard C Library, P.J.Plauger.
      - C Traps and Pitfalls, Andrew Koenig.

------
prog
I found "The Complete C Reference" by Herbert Schildt to be quite good. Most
of the language is covered in about 250 pages followed by standard library
function, algorthims and data structures and ends in a good project "The
Little C Interpreter". Its about 800 pages but then its a reference so you
don't need to read it in one go :-)

~~~
tptacek
comp.lang.c hated Schildt so much they made a FAQ entry for him (though I
admit I've never read one of his books).

------
numeromancer
Try this:

<http://www.eskimo.com/~scs/cclass/cclass.html>

Once you can stand on your C legs, you should read the C-FAQ, here:

<http://www.c-faq.com/>

and get a copy of the C99 standard. It's supposed to be here:

<http://www.dkuug.dk/JTC1/SC22/WG14/>

but the site was unavailble when I tried to check it before writing this
comment.

Various C-related stuff that is good to read:

<http://www.lysator.liu.se/c/duffs-device.html>

<http://www.lysator.liu.se/c/ten-commandments.html>

<http://www.lysator.liu.se/c/pikestyle.html>

Take this with a pinch of salt:

<http://www.seebs.net/faqs/c-iaq.html>

~~~
benster222
K&R, the definitive reference and Expert C Programming:Deep C Secrets by Peter
van der Linden

Because the best way to understand a language (and its ups and downs) is from
someone who understands that language's compiler.

------
gcv
After K&R, I highly recommend Peter van der Linden's Expert C Programming
([http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp...](http://www.amazon.com/Expert-Programming-Peter-van-
Linden/dp/0131774298)). It's fun to read (yes, really), and you'll understand
the language better for it. C is fairly quirky, and this book helps navigate
those quirks.

For example, I bet most people who claim to "know" C can neither explain the
difference between arrays and pointers, nor clarify where they cannot be used
interchangeably. I was lucky to have read that book early on in my days of C,
so I actually know the answer.

------
gte910h
This post only contains non-aff links

While I'm certainly good at C, and have been the guy people asked the C and C
toolchain questions at a couple places I've worked, I'd say you're in for more
than 1 book to grok the topics you've expressed interest in, and haven't met
the single book that does all you want.

1: If you're a python programmer, I do suggest staying with pure C and AWAY
from C++. You have little use case for it if you can mix python and C and it
is literally pain incarnate while you do not know every little bit of it
and/or work with people who do not know every little bit of it.

2: Secondly, a single book on C will not get you where you're going. You will
need several.

3: I'd stick with K&R for reference, but then go to the following two books
for threading and all the other stuff like networking:

You need these two books to get down C and it's ecosystem (make, autotools,
etc): Advanced Unix Programming by Rochkind (Really good explanation of
signals especially): [http://www.amazon.com/Advanced-UNIX-Programming-Marc-
Rochkin...](http://www.amazon.com/Advanced-UNIX-Programming-Marc-
Rochkind/dp/0131411543/ref=sr_1_1?ie=UTF8&s=books&qid=1269362485&sr=8-1)

Gnu/Linux Application Programming by M. Tim Jones (Recovers some of the same
stuff as AUP, but does better with the toolchain): [http://www.amazon.com/GNU-
Linux-Application-Programming/dp/1...](http://www.amazon.com/GNU-Linux-
Application-
Programming/dp/1584505680/ref=sr_1_1?ie=UTF8&s=books&qid=1269362580&sr=8-1)

If you want to go more advanced, this is likely the correct book: Advanced
Programming in the Unix Environment: [http://www.amazon.com/Advanced-
Programming-UNIX-Environment-...](http://www.amazon.com/Advanced-Programming-
UNIX-
Environment-2nd/dp/0201433079/ref=sr_1_2?ie=UTF8&s=books&qid=1269362485&sr=8-2)

Although if you're diving deep into networking, this is likely the correct
book: Unix Networking Programming: Vol I by Stevens:

[http://www.amazon.com/Unix-Network-Programming-Sockets-
Netwo...](http://www.amazon.com/Unix-Network-Programming-Sockets-
Networking/dp/0131411551/ref=sr_1_1?ie=UTF8&s=books&qid=1269362819&sr=1-1)

------
bballant
I will second the vote for Mastering Algorithms in C. This book will bring you
right into the details you want: [http://www.amazon.com/Mastering-Algorithms-
C-Kyle-Loudon/dp/...](http://www.amazon.com/Mastering-Algorithms-C-Kyle-
Loudon/dp/1565924533)

Accelerated C++ was also mentioned and I just love this book. It brought me
back to C++ after years of being away: <http://www.acceleratedcpp.com/>

------
Apreche
Pointers on C helped me really understand pointers like no other book was able
to do.

[http://www.amazon.com/Pointers-C-Kenneth-
Reek/dp/0673999866/...](http://www.amazon.com/Pointers-C-Kenneth-
Reek/dp/0673999866/ref=sr_1_1?ie=UTF8&s=books&qid=1269356298&sr=8-1)

------
adrianscott
If you really want to do Python modules, I can understand.

In terms of hacking small Unix tools, have you considered other options like
perl, bash, combo's of unix commands, etc.? I suggest that those options could
be a lot more productive for your time investment than C. IMHO. Hope this
helps.

~~~
nailer
The only time I'd bust out C is when there's no Python API (meaning there's
probably no Perl API either). I generally avoid shell scripting these days as
I find text processing a fragile way to build something useful.

