Ask HN: Examples of especially well-written C code?

21 points by dlowe ↗ HN
In light of the recent OpenSSL rant (http://news.ycombinator.com/item?id=1680337): what are some open source projects written in C which are particularly well-written?

I can give one example: I was very pleasantly surprised by the experience of cold-reading the BerkeleyDB source (trying to explain some very odd observed behavior) a few years ago. The code was laid out in a sensible way, such that I could find what I needed reasonably quickly. It was generally clear and straightforward to read, and the few places with "tricky" code were very nicely commented -- including the source of the odd behavior I was hunting for.

Are there other examples of great, readable C code out there?

18 comments

[ 4.9 ms ] story [ 186 ms ] thread
I've been told that the Tarsnap source code is particularly good. :-)
(comment deleted)
i really liked the redis codebase. not sure if its changed much since it became a much bigger project, but back when it was mainly @antirez, it was some of the cleanest code i've ever read.
In the past, I've found the code for SQLite to be brilliantly clear: http://sqlite.org

Going further, I'd suggest that most large successful projects in C have clear code that is worthy of study. It's some corollary of the anthropic principle --- if the code wasn't clear, it would never have survived to become successful.

This may only apply to the core of these projects (written by experts) than to the periphery (written by learners). But you might be surprised by how readable the central code is for Apache, Linux, Glibc, Mysql, Perl, Python, etc.

I second SQLite. They even have the entire source concatenated into a single file, which means you don't have to use ctags (or equivalent) for jumping around the project.
In most nontrivial projects, C is used to solve problems that are worse being solved with other platforms: targeting the biggest possible platform independence but caring about performance. So you can't compare the "beauty" of something that is supposed to run on my 50 USD router with 32 MB with something that has not much to do (measuring CPU and memory use) and has the luxury to be compiled only by a few compilers.

Another problem is that a lot projects "grow" without any vision. Once you understand that, you'll find that most of the successful C projects didn't have much more choice, more because of the history of them than anything else.

However when you have the full control of the platform and have a small numbers of the developers with a good taste (you control the OS and the compiler too) you can maintain "beauty" consistently. In this regard, I suggest you to enjoy Plan 9 sources!

http://plan9.bell-labs.com/wiki/plan9/Sources_repository/ind...

Redis is wonderfully well written.

http://github.com/antirez/redis

I love working with the redis codebase. In my opinion, redis is beautiful for a few reasons.

It's written in an object-oriented style (i.e. structs are "objects", each C file is a "class", and function prototypes are consistent for constuctors/destructors/instance methods). Also, everything is modular in redis (i.e. you can take the redis string or network library and use it in another project without any problems).

I also like the fact that it's portable C (C99 IIRC) that just requires make (no autoconfiguration necessary).

easy tasks are easy to understand

hard tasks are hard to understand

Good programmers can read bad code. I think SSL is likely to be obsficated?

PostgreSQL and the Linux kernel sources make great reading materials.
I would recommend David R. Hanson's book C Interfaces and Implementations. It is an extremely well documented library and shows you how to design APIs properly.

http://www.amazon.com/Interfaces-Implementations-Techniques-...

I'd second that. Beyond just getting a good code base, it's quite likely that you get some good ideas for APIs and algorithms.

Beyond that, Tcl/Tk is a large-ish codebase that's still quite manageable, especially considering its age and the many rewrites.

For a more idisyncratic view, I once went through Rob Pike's sam editor. No header guards, sparse comments, short variable and function names. But you could still figure out what's going on without any problems. That was the old portable sam, don't know if the current plan9port one is still that good.

Based on the recommendations here, I just got this book by interlibrary loan. I haven't read much of it yet, but I'm glad I didn't buy it sight unseen. It's an understatement to say does not meet the expectations I had for it. Perhaps one could develop a good course around it, and I'm sure there are good things an experienced coder could gleam from it, but as a standalone text for a beginner I think it would do more damage than good.

I thought at first that the code samples he was giving were examples of "what not to do", and then was astonished to find him defending them in the text. From page 36, after some horrendous code for Atom_int() page 35:

"When the conversion is done, s points to the desired string, and this string has &str[43] - s characters. str has 43 characters, which is enough to hold the decimal representation of any integer on any conceivable machine. Suppose, for instance, that longs are 128 bits. The string representation of any 128-bit signed integer in octal - base 8 - fits in 128/3 + 1 = 43 characters. The decimal representation can take no more digits than the octal representation, so 43 characters are enough.

The 43 in the definition of str is an example of a 'magic number,' and it's usually better style to define a symbolic name for such values to ensure that the same value is used everywhere. Here, however, the value appears only once, and sizeof is used whenever the value is used. Defining a symbolic name might make the code easier to read, but it will also make the code longer and clutter the name space. In this book, a symbolic name is defined only when the value appears more than once, or when it is part of an interface."

I'm glad to see his priorities presented in such a clear manner. If you feel that your current code is too readable at the expense of "name space clutter", this might be a good book for you. But otherwise, just say no!

ps. In case this example didn't convince you, the following chapter on using setjmp() and longjmp() to roll your own macros for exception handling might be worth glancing at in the online version before you confirm your purchase.

I'm a fan of parts of the BSD kernel myself. My first exposure was through the book "The Design and Implementation of the FreeBSD Operating System". Then again, dorking around in kernels and the like hold some interest for me.
I'm a fan of parts of the BSD kernel myself.

I hope you don't mean that. The bits of original BSD which are still in the FreeBSD tree are pretty ugly -- recent FreeBSD code is much better.

Python's C code is pretty well written. Plus it can be useful to know about if you actually write Python.
Do you mean something like this?

            main(l
       ,a,n,d)char**a;{
   for(d=atoi(a[1])/10*80-
  atoi(a[2])/5-596;n="@NKA\
 CLCCGZAAQBEAADAFaISADJABBA^\
 SNLGAQABDAXIMBAACTBATAHDBAN\
 ZcEMMCCCCAAhEIJFAEAAABAfHJE\
 TBdFLDAANEfDNBPHdBcBBBEA_AL\
  H E L L O,    W O R L D! "
    [l++-3];)for(;n-->64;)
       putchar(!d+++33^
            l&1);}
(source: http://www.ioccc.org/years.html#1992_westley)