
Ask HN: Learning C - FiveFiftyOne
Throughout my career, I've viewed C as the sleeping monster that mere mortals such as myself dare not waken. However, as I increasingly seek to achieve more complex goals in my projects, I find myself encountering C libraries (such as GMime) which will answer all my questions, if I could actually program in C. I have a copy of C Primer Plus Fifth Edition at hand, a development FreeBSD server as well as my Mac, but would like to ask of this community if they are aware of any other references, such as old CS course materials, which may help. Many thanks in advance. I realise that this is a long term goal, but feel that with my taste in server platform and operations software, C will prove a boon to me.
======
rsheridan6
Just about everybody who answers this will say that K&R is good, and I agree,
but in addition to this I found that learning the basics of assembly was
helpful. You can really see what's going on with the stack, what a pointer
really is (pointers are really the only tough part about learning C,
everything else will be the same old same old if you already know how to
program), and the difference between a system call and a regular function
call, and it doesn't take much time to learn.

Books by W. Richard Stevens were old when I was learning, and older now, but
they were the best guides to taking it to the next levels. You can pick up a
lot of tricks and stylistic pointers from him while learning about UNIX
features and networking. Maybe somebody will chime in with a more up-to-date
resource that does the same thing.

~~~
screwperman
I'd second this. In fact, Steve Yegge once said this about K&R (
<http://steve.yegge.googlepages.com/ten-great-books> ):

 _This is an odd little book. It's frequently mistaken for an introductory
programming book, which inevitably leads to frustration. It's not a good way
to learn how to program; it expects that you're already familiar with machine
architecture, assembly language, compilers, and at least one other high-level
language.

It's not even a very good way to learn C. The idioms and best-practices for C
programming have evolved substantially, even since the second edition was
published, and some of the code samples look a bit dated._

As the parent said, you'll appreciate C only if you learn about machine
architecture and Unix. Diving into a large codebase will get you acquainted
with "modern" C.

I've found the book _C Traps and Pitfalls_ to be _the_ book to get you to
think like a C programmer. _The C Puzzle Book_ is pretty good for exercises,
and _Expert C Programming_ does a good job exposing the ugly side of C.

~~~
jfarmer
I know the plural of anecdote is not data, but my personal experience was the
opposite. C was the first programming I learned and I learned it by reading
K&R in high school. I certainly didn't know anything about assembly,
compilers, or another high-level language.

From there I learned by contributing to open source projects.

Not saying K&R is the best way, but it's not _so_ opaque that a beginner with
zero knowledge of C (or even programming) can't pick it up and learn if
they're motivated to learn it.

~~~
SwellJoe
K&R was the only C book that ever allowed me to pierce the veil of mystery
surrounding C and understand it. I'd tried at least a half dozen other books
and was either bored out of my mind at the painfully slow pace, or utterly
baffled around chapter 2 or 3 where it leapt into pointers and seemed to just
assume it was obvious.

For whatever reason K&R was a perfect storm of comprehension for me, and I
came away actually knowing how to read and even sort of write C (and knowing
how to search the Internet, pre-Google, or ask reasonably smart questions on
the mailing list or IRC channel of the software I was working with, for
answers to the harder questions). I failed miserably with every other book on
the subject.

------
tumult
C isn't hard, don't worry! It's actually a fairly simple language. But it's
medium/low-level and there is a lot of power within its simplicity. Fast to
learn, but a long time to master, as one might say.

I don't know what people are using to learn C these days, but the standard has
always been the white book [http://www.amazon.com/Programming-Language-
Prentice-Hall-Sof...](http://www.amazon.com/Programming-Language-Prentice-
Hall-Software/dp/0131103628)

You will find yourself spending more time thinking about programming concepts
rather than dealing with C syntax, since it's pretty concise. I don't know how
difficult it is to learn about pointers if you have already been programming
for a while but haven't had to use references directly, but it's very
important to learn. C does not do too much for you on its own, so handling
references yourself is an important skill. It will also help you understand
how higher level languages and concepts work.

If you are working through it and find that you're enjoying yourself,
congratulations, you're a programmer :] Then it's time to pick up the 1st
volume of Knuth and start working through that.

~~~
baguasquirrel
Indeed, the problem with C is just that. Once you understand how it works,
you'll realize it's just a thin abstraction layer over assembly language. It
really is just that simple. My last job was almost purely C, and what made C
"scary" at times were:

1\. naming conventions. I don't know why C programmers use the strange names
that they do.

2\. macros. C macros are a pain to read and follow.

I hope things will be easier to learn if you know this going in, because
that's really all there is to it.

The catch with C is that while it is simple, writing good code with it is not.
You have two tools for metaprogramming: macros and function pointers. C++
classes seem evil, until you see what people do in C in the absense of any
mechanism for polymorphism.

Thankfully for you, you probably will only ever need to deal with libraries,
not applications, so you'll never have to deal with the hell that comes with
trying to use C for higher level work.

~~~
rthomas6
They use the strange names that they do because a function declared in C is
declared everywhere in the whole program. They use strange names to try to
stay out of your way; i. e. it would be really bad if two functions had the
same name.

~~~
Daniel_Newby
You're right that C's lack of namespaces makes for funky names. However, note
that "static" functions are visible only within their compilation unit, which
can bring some order to the madness.

~~~
baguasquirrel
Yes, exactly. And yet people continued to use the unhelpful, oblique prefixes
and suffixes they used for global symbols nonetheless.

------
mahmud
Best beginner text after K&R is Kelly and Pohl's "A Book on C"; very newbie
friendly and at the same time uses traditional C examples (i.e. memory
management, serializing and reading-back record-oriented data stored in
structs, file and directory manipulation, string manipulation, etc.)

Most other C books will just treat it as a stepping stone for C++ which is a
different beast, and a few awful offenders will stretch it to Java!

To see a few Algorithm implementations in C, there is no better friend than
Robert Sedgwich's polyglot tome; it's the applied Knuth volumes that everyone
keeps on their desk (quickly swapped for the actual Knuth volumes when
expecting hacker guests.)

Along with C materials you will also need Unix materials. The two are
inseparable and fuel each other. You already have a decent Unix in your Mac,
and your FreeBSD is the best of the Unix breed bearing the original blood. For
that there are no better companions than the books by Richard Stevens, both
for system and network programming.

For larger scale software engineering you will need a few small to mid
projects of your own. You will deal with header file and Make dependency
problems, a few unix and processor portability problems and a few other stuff.
The solution to those problems along with a fat library of useful routines are
found in "C Interfaces and Implementations" by Hanson. It's a literate
programming text where source code is interwoven with prose documentation and
it's very self evident.

Along with productive C programming you might need to look into the darker
side of C and Unix and follow the papers of the hacking underground (yes,
HACKING, dispute the terminology all you want, but I think some blackhats
deserve the noble noun more than javascript and CSS jockeys.) Unix and C have
plenty of Not-TODOs to motivate plenty of caution. Hoglun and McGraw's
Exploiting Software is the canonical C-Do-Not text books.

If you want to read library source code, your FreeBSD source code should give
you plenty to keep you busy. Start with the sources for the games; I spent an
enjoyable summer porting Minix games to DOS and taught me allot. There is also
"The Standard Function Library", or SFL, google it, it has the cleanest C
sources you ever seen. Highly recommended.

And should you ever want to write a C compiler, like I attempted, here is some
advice: implement Oberon instead. Everything you could possibly learn at
1/100th of the headache.

Just the 2 cents of a guy who will only write C code again if there was a gun
to his head ;-)

~~~
FiveFiftyOne
I actually picked up and then put down a good looking book on Unix systems
programming either by Stevens, or by someone who worked very closely with him
and wrote an updated version. I think I'll scream off to the book store and
track it down.

~~~
mahmud
It's the updated version of APUE done by Rago (the guy who did Unix System V
Network Programming; a fairly good book but with a narrow and almost obselete
focus; sysv STREAMS -- a very good idea whose time hasn't come.)

------
neilc
You should absolutely learn C. A good knowledge of C is a very valuable asset
for all sorts of work, especially on Unix.

Thankfully, C is straightforward to learn. The major concept you need to
understand is pointers; once you've done that, there are some syntactic
oddities to absorb (typedefs, function pointer syntax, arrays vs. pointers),
and you should skim through the standard library (which is tiny compared to
Java, or even C++), and you're most of the way there.

In addition to K&R, I've hears that Steele and Harbison's "C: A Reference
Manual" is very good, although I haven't read it personally.

~~~
dnewcome
I have Steele and Harbison's "C: A Reference Manual", and _is_ very good, but
probably not for _learning_ C. It does have very good explanations of some
under-the-hood things that I haven't found elsewhere. It is also a good
reference on the C std library, and does a good job at pointing out possible
incompatibilities between ISO C, `traditional' C, and vendor-specific
dialects. One of the things that I have always found confusing about C is that
code can be written in several ways, depending on how lax the compiler is
about enforcing different versions of the C standard.

------
cschep
A great resource I have enjoyed while brushing up my C skills has been CS107
at Stanford University on the web.

<http://www.stanford.edu/class/cs107/>

You can find the lectures on academicearth.org, or on iTunesU if you prefer to
download them that way.

Jerry Cain is a great lecturer. I wish they'd post the assignments with the
files they provide the students though. Maybe someday.

~~~
natrius
FYI, CS107 has changed considerably this year, so the course description on
the current course site is a bit different from what you'll find on Academic
Earth.

<http://academicearth.org/courses/programming-paradigms>

------
kmavm
First, congratulations. You're making the right decision. Programmers who are
ignorant of C leave certain roles and problem domains closed off to them. Even
if your primary language is something else, not being afraid to roll up your
sleeves and fix performance and correctness problems in the compilers and
runtimes themselves makes you more valuable, more confident, and better able
to reason about how the runtime will map your input to the machine. And
proficiency with system-building languages and tools is a prerequisite if you
ever aspire to be a "head surgeon," "10x programmer", "ninja", or whatever the
heck the kids are calling it these days :).

K&R et al. are fine, but I'm a particular fan of two slightly oddball, but
great, books about C:

1\. van der Linden's Deep C Secrets. Short of implementing a C compiler
yourself, reading this book is the surest path to completely understanding
some aspects of the C linkage model, and the distinction between arrays and
pointers. It's also entertainingly written, which always helps.

2\. The Lions Book, an annotated source listing for the Unix v6 kernel. The
subject matter is one of the most beautiful and influential programs ever
written. This ~10k-line program is completely understandable in six weeks'
study, a couple months' tops, yet it staked out almost all of the abstractions
that still underly modern operating systems. It is also C's native
environment: C was literally invented to write this program. And while it's
dated in some of its peculiarities ("=+" where we'd write "+=", identifiers
only being significant in the first 8 characters, no typedef yet, a lot more
reliance on the register keyword, etc.), it's damned fine code, by any
standard. Each page brims over with good, informed engineering trade-offs; the
sweet spot may have shifted since the days of 128k core and 16-bit CPUs, but
the thinking that goes into those trade-offs is mostly unchanged.

------
twopoint718
This falls more into the "tips and tricks" category, but I wish someone had
mentioned this to me earlier. Once you have a good book on C[1] install all
the man pages for the standard library. Once you start writing code, being
able to say something like "man strlen" is amazingly useful.

I made the most progress in C when I took a class on OSs. Mainly, we wrote
systems programming sorts of things like a simple shell, our own version of
malloc, a simple user-space thread library, and so on. This really gave me
insight into how these things would be done for real. Also, writing something
really linked-list-heavy gets you a feel for pointers _really_ quickly.

[1]: I have K&R ANSI C and I found it very concise and well-written. It is
probably one step up from the "raw newbie" class of books in terms of
difficulty, but should feel just right for someone already acquainted with
(an) other language(s).

------
antirez
You should learn C. It is a small language but to master it requires a lot of
work for a reason: you need to get good at design. When all you have in your
hands are structures and pointers you absolutely need to develop the ability
to design well organized programs in different layers of abstractions,
otherwise to scale over the 1000 lines of code program is almost impossible.
This is probably the most valuable thing C will teach to you.

------
tptacek
1\. In Which I Join The Choir

You should definitely learn C:

* You'll learn the memory hierarchy, which is probably the most important thing to know about performant software.

* You'll get 100x better at debugging --- both because you'll have practice, and because most of the tools you use to debug C code work for higher-level languages (gdb is still a better Ruby debugger than Ruby's own debugger).

* You'll be able to bridge Python (or Perl) to almost any library or framework you ever need.

2\. In Which I Express Reservations

 _Don't learn assembly._ In my (C and assembly-heavy) career, I've found it
works in exactly the opposite direction: you won't really understand assembly
until you understand C code. There are mainstream architectures (SPARC and
MIPS) that are literally designed as drivers for C compilers.

You'll eventually want to be conversant in assembly so that you can debug
faster (when it comes to the runtime, the C language is a flimsy abstraction
indeed). But you should let your needs and interests drag you into the
machine, just like you should probably learn "Stairway" and "Smoke On The
Water" before mastering barre chords and sight reading --- you can have a
pretty excellent punk band without ever knowing how to read music.

3\. There Are Books

Everyone is going to have an opinion about K&R. What I think you need to know
is, it's short and it's dry. I re-read it 6 years into my career and I was
surprised at how rich it was; there's a lot of design and data structures
material, beyond the core language.

There's a C book that changed my life. It's David Hanson's "C Interfaces And
Implementations" (CII). I will now make a case for why it's the first and only
book you'll need. You're coming to C from a high-level language. That language
is giving you a couple key things you don't realize you depend on:

* Garbage collection

* Lists and hash tables

* Resizeable strings

Almost every major C project contains a site-specific reimplementation of
these concepts. CII gives you one --- an internally consistent one, relatively
well implemented, and extremely well documented. In doing so, it also teaches
you the single most important thing about writing good C programs, which is
how to build abstractions around your gnarly code.

The difference between people who know C as a language and people who can
actually deliver software in it is resizeable containers (linked lists,
dynamic memory allocation, high-level strings, doesn't really matter what the
specific is).

The other book you want is "Advanced Programming In The Unix Environment" (or
its moral equivalent, "Win32 Programming").

CII is "how". APUE is "what".

Finally, I like (for new programmers) "The Practice Of Programming".

4\. What I Did To Get Started

I "knew" C for a while (maybe since I was 13) before I actually started coding
in it. Two things got me unstuck.

First, I picked a couple basic Unix APIs and wrote little toy programs around
them. If I remember correctly, the first thing I wrote was "who", from
"getpwnam(3)", which forced me to do some basic strings and structure
pointers.

Second, I wrote network code from a socket tutorial. Sockets are a great thing
to get started on; just write a scraper for a service you like, and there's a
zillion little problems you'll have to solve that are the same problems you
solve in every other program you write.

~~~
jdybnis
I violently disagree with not learning assembly. Absolutely learn assembly.
Just pick anything else other than x86 assembly. After learning the basics of
assembly you will never have any trouble understanding pointers or any of the
"hard" concepts in C.

x86 is a convoluted horror. A lot of it makes no sense except in the context
of backwards compatibility, which the documentation won't necessarily point
out. I highly recommend picking up a microcontroller to learn on instead of a
microprocessor. Microcontrollers are mostly self-contained systems, while
microprocessors are just a small piece of the picture and have complicated
interfaces to the rest of the system components.

I recommend picking something in the Freescale 68HC* family. The addressing
modes and instruction set are fairly clean and the architecture is simple.
Something based on ARM would probably also be straightforward to learn. Don't
worry about choosing a 32 bit chip, 8 or 16 bit is fine. 8 and 16 bit chips
are typically simpler and will still teach you the important concepts.

Spend a couple of weeks on this and your understanding of C will be easier to
come by and more thorough.

~~~
duskwuff
I'd steer away from the really small microcontrollers, as they tend to be
register-starved (and/or memory-starved!) enough that you have to make ugly
compromises, particularly in the area of call stacks. :(

ARM, PowerPC, and MIPS are all good choices if you've got appropriate hardware
to play with. All three are nice, clean RISC architectures with plenty of
registers and sane addressing modes.

~~~
eru
Or try your luck at Core Wars. There you write programs in a simple assembler
(Red Code) to fight against each other i.e. make your opponents execute an
illegal op-code.

------
wooby
1\. K&R - an absolute essential. I found myself in your shoes about two years
ago, picked this up, and worked through it.

2\. "The Unix Programming Environment" ([http://www.amazon.com/Unix-
Programming-Environment-Prentice-...](http://www.amazon.com/Unix-Programming-
Environment-Prentice-Hall-Software/dp/013937681X)) This is a recent find, but
covers more application. It's almost a Part 2 of K&R and covers building
problems and the Unix signal and file APIs. The examples are in an ancient
syntax, but part of the fun is coding them and getting them to compile.

3\. "The C Puzzle Book" (<http://www.amazon.com/Puzzle-Book-Alan-R-
Feuer/dp/0201604612>) I found this one day at Fry's, and it's fucking awesome.
You can effectively learn C using it without a compiler.

Good luck!

------
makecheck
K&R
[http://en.wikipedia.org/wiki/The_C_Programming_Language_(boo...](http://en.wikipedia.org/wiki/The_C_Programming_Language_\(book\))

------
astine
I taught myself C/C++ when I was around 13. I already knew most of the
concepts through my experience with Pascal, including pointers, which are
harder to use than to understand. What I did have trouble with was Windows as
I just couldn't figure out the API. What solved it for me was one of those old
'Game Developers' series of beginner's books. It gave detailed instructions on
for a 'hello world' Windows application. After that, it was pretty easy to get
the hang of it.

I don't use C much anymore (haven't since Highschool.) When I do, it's with
GCC and I and the environment is still the hardest part.

Moral of the story being that C is pretty easy. I learned it with some very
basic references. The hard part, supposedly, is pointers, and those are much
harder to use than to understand. Basically, everything is done through them,
without the usual abstractions that you would get with say, Java. You mainly
just have to make sure you always have the right number of asterisks and
ampersands.

One book I can suggest is _Advanced Programming in the UNIX Environment_ by W.
Richard Stevens, (revised version) which gives a very through introduction to
UNIX from a C perspective. C is interesting in that it is almost a different
language depending on which system you write it on and you'll spend more time
learning system calls and UNIX paradigms than C syntax and pointers.

------
avinashv
I learned C a while back, and don't regret the time spent doing so at all.
This is how I'd recommend going about it:

* Everyone is going to recommend K&R, which is fine. Find a copy of C Interfaces and Implementations as well--very good implementations with explanations of standard high-level structures.

* Read source. SQLite's source, for example, is very well written and documented, and they actually have a version to download recommended for reading (everything is in one file).

* Implement. You're going to want to try implement standard Unix commands yourself. Try writing an interpreter/compiler as well. These things give you a good grip on a wide variety of C basics and will make sure you can work well with memory management and all that.

* Assembly. This is where _I_ would learn assembly (i.e., where I did). I don't think you need to go too far in depth, but a basic working knowledge will make debugging much, much easier.

~~~
hello_moto
Hi avinashv, I'm interested to learn SQLite. I noticed you mention that there
is a "recommended for reading" version of SQLite. Would you mind pointing out
where I can find it? I browsed the website and haven't had any luck to find
such information. Thanks!

~~~
avinashv
It's just the "amalgamation" version off <http://www.sqlite.org/download.html>
(it's the first download link).

~~~
hello_moto
Thanks!

------
radu_floricica
Chances are you already know C, but don't realize it. Java and PHP have mostly
C syntax. All you have to do is substract objects and add pointers.

Like rsheridan6 said, assembly helps. It's not necessary though, as long as
you realize a pointer is actually a memory address and not something abstract
like a reference in Java or PHP.

~~~
davidw
... and figure out how to deal with allocating and freeing things. Taken
together, pointers, and manual memory management are a big chunk to bite off.
The syntax isn't the problem, in other words.

~~~
silentbicycle
For sake of argument: How often is the syntax the _primary_ problem in
learning a new language?

The examples that come to mind are Forth and APL/K/J (all of which I've only
dabbled in), but the reason they have such unconventional syntaxes is because
they're conceptually very different.

~~~
radu_floricica
And yet, because of the syntax I don't remember learning PHP. It was pretty
much one night of reading the manual to get to know the API, and that was it.
They're close conceptually too, not just in syntax.

------
voberoi
If you've got the time, I _highly_ recommend taking CS107 at Stanford (for
free):
[http://see.stanford.edu/see/courseinfo.aspx?coll=2d712634-2b...](http://see.stanford.edu/see/courseinfo.aspx?coll=2d712634-2bf1-4b55-9a3a-ca9d470755ee).

I became incredibly comfortable with C -- memory management, handling
pointers, having a very clear picture of how types are represented in memory
-- after taking that course. The lecturer (Jerry Cain) is fantastic as well.

The course changed this year so I don't have any thoughts on the current CS107
offering if you plan on taking it through their online course offerings for
pay. The lectures, syllabus, and materials on Stanford Engineering Everywhere
(OpenCourseWare at Stanford) are all from the course I took two years ago.

------
SwellJoe
C Primer Plus was completely useless to me. As I mentioned in another thread,
I tried several books on C before K&R and none of them "took". I knew (by some
definition of "knew") other languages (several BASIC variants, Pascal, REXX,
Amiga shell, a little 6502 and 68000 assembler, etc.) when I started learning
C...but it took years, and several failed attempts before I was actually able
to make sense of real C code.

My book recommendations would be K&R, _Advanced Programming in the UNIX
Environment_ by Stevens, and _C: A Reference Manual_ by Harbison and Steele.
In that order. With liberal doses of web research and reading real world
examples and experimentation.

------
miles
Learn C at Harvard (virtually) for free:

[http://tinyapps.org/weblog/misc/200904120715_learn_c_for_fre...](http://tinyapps.org/weblog/misc/200904120715_learn_c_for_free_at_harvard.html)

------
plinkplonk
Here is what worked for me.

Work through, in order, (1) K & R (2) C interfaces and Implementations by
David Hanson (3) Deep C Secrets by Peter Van der Linden (4) Advanced
Programming in the Unix environment

Good Luck!

------
spc476
I've only found two books on C worth the money. One is K&R, the other one
(which I haven't seen mentioned here) is "The Standard C Library" by P.J.
Plauger. It not only presents the ISO standard for the library, but Plauger's
commentary on the standard, how to implement the standard C library, along
with his implementation. It explains some of the murkier aspects of the C
library, along with how to go about writing portable code.

------
JeremyChase
If you can program well in C, everything else seems like both a blessing and a
compromise.

While K&R is great, my copy is far less used than Pointers on C by Ken Reek.
If you can find a cheap copy I highly recommend it. If you are working through
K&R make sure to do each of the sample problems. The text is just the support
to let you figure out how to do them.

------
mavelikara
I also wanted to learn C, not to learn specifics of the language per se, but
to better understand the C/UNIX ecosystem. The book I chose to follow was
Computer Systems: A Programmers Perspective. You can get a draft at:
<http://lsec.cc.ac.cn/~tcui/download/draft.pdf> .

------
colonhyphenp
This course website from the University of Maryland has a very good
introduction to C.

<http://www.cs.umd.edu/class/fall2005/cmsc212/>

It starts off with the fundamentals then gets into some more advanced
principles. In particular, check out the "Jan Plane's Lecture Outlines" link.

------
rubentopo
Stanford's CS Ed library (particularly Nick Parlante's linked list and binary
tree problem sets) is a fantastic resource for understanding the C language,
it is the way i learned it.

<http://cslibrary.stanford.edu/>

------
FiveFiftyOne
Well, copies of K&R and C Puzzle Book are on their way, with CII and Advanced
Programming In The Unix Environment (2ed) wishlisted for later. Can't find a
copy of Deep C Secrets on our local Amazon equivalent, but I'll keep
searching.

------
pasbesoin
It may not be what you are looking for, but if you want a C based intro CS
text, this classic is now freely available.

Foundations of Computer Science

<http://infolab.stanford.edu/~ullman/focs.html1>

------
mlLK
Some helpful reminders for learning any programming language,
<http://c2.com/cgi/wiki?LearningProgrammingLanguages>.

------
ohfour
I bought K&R but in the end found <http://www.cs.cf.ac.uk/Dave/C/> to be much
more useful and accessible - and free!

------
Zarathu
Sure! Knowing C can definitely help with your overall understanding of how
things work. It's especially helpful when learning new languages.

I uploaded a copy of K&R ANSI C for you. In my opinion, it's probably the best
way to learn it.

<http://whitepaperclip.com/files/ansi_c.pdf>

Have fun!

~~~
pmarin
This book have copyright and you can buy it in libraries.

~~~
jcapote
What makes you think he's not?

------
anthony_barker
amazon booklist I used to teach myself

<http://www.amazon.com/Master-C-Programming/lm/9PUKX2J9RNUO>

------
FiveFiftyOne
Brilliant. Thank you all.

------
mroman
I will be trying this myself, from what I can see it would be very helpful for
learning C:

<http://bellard.org/tcc/>

