Why K&R C is a Must-Read
Tagged: readings learning linux programming thoughts
In 1988 Brian Kernighan and Dennis Ritchie released the 2nd edition of "The C Programming Language" (better known as "K&R C"), a must-read for any serious programmer. It is praised in reviews, random HN posts, and in books like P. Seibel's excellent Coders at Work amongst others. Is reading it solid advice or is it a product of a cargo cult? I decided to find out.
The book's small size, slightly less than 300 pages, of which around 190 are the core material, masks a mountain of knowledge. I promised myself that, to grok everything, I would do every exercise and that it "shouldn't take me more than two or three weeks." That was on a fine April day. So I read the text, I did every exercise, I compared my code to other's solutions, when, on the last day of September, I bumped up against the appendix. This could have been compressed into a month's worth of focused study were it not for client work and other happenings in the real world. My motivation would ebb and flow, but the clear writing and interesting problems helped me get to the end.
The book contains many exercises, most of them small, 30-minute things. Taken allogether, they amount to roughly 6500 lines of C and progress from "substitute all substrings in a string" to "recursively read directory inodes to get each directory's files' names and sizes". I underestimated the time to complete an exercise the first few times; this humbled me. My first big wakeup call was that, in C's procedural style, my ways of managing state, learned through OOP and a bit of FP, were useless. There were other challenges as well: managing memory manually, handling low-level input, referencing and dereferencing memory using pointers, and figuring out the meaning of a few anachronisms like "tabstops." All sunk-cost fallacies aside, what did I get out of this?
I can finally explore everything ever written in C. This isn't normally a strong selling point of learning a programming language. Just today I chanced upon this great post about what really happens when you instantiate a Python class. Python's default implementation, CPython, is written in C, so I was able to follow and understand the code that's run when you
Foo(a, b). A few days earlier, I used this newly found superpower to have a look at some venerable Linux utilities like cat, cp, and netcat. It blew my mind to read programs written before I was born. I can't decide whether I should buckle down and read CPython's source, or the legendarily good redis code, or maybe, out of nostalgia's sake, grok Quake 3 Arena. The world just became more open and interesting.
Knowing even a little bit of C strips away many layers of abstraction from the world; it turns the abstract into the mechanical: "get me 12 bytes of memory, write 12 bytes of data (no more!) in there, now hand its address over to a function." It pushes me to ask questions: how does Python allocate memory for lists and tuples? How does Linux "watch" your files for modifications? How is a JS associative array structured in terms of raw bytes? What kind of system calls happen when you run a script? I put on my lab coat and safety goggles and go at it with strace and gdb like I would with a microscope or petri dish.
"So you're telling me, that after all that time and effort, you're essentially a software archeologist with better debugging skills?", you may ask.
Yeah, how awesome is that :)? But if that's not enough - after K&R you're ready to do one more thing. See, since C is so widespread, you're likely to be working with software that can be extended or modified using it. In my little part of the woods, the popular thing to do is to write Python or Postgresql modules in C when the task at hand demands speed. Why not take it further and write your own nginx modules? Or, using Lua's source as a guide, write a simple interpreter?
You'll get by without K&R. Even live a happy and productive life, too. But reading it will allow you scratch that itch when you're looking at the screen, palms on your temples, and muttering "why does this thing..."