Why you need to learn C (Director's Cut)
[Note: This is written with Ruby programmers in mind, but it applies to anyone using similar high-level languages]
[Note 2: After sitting on this post for a day and getting some feedback, I’ve decided to rewrite and extend it a bit. See the old version here]
Most modern high-level programming languages shroud the hardware executing their programs in several layers of abstraction. Programmers don’t care much about the machine any more, having been taught to leave all the messy details to the interpreters, compilers and virtual machines.
So, C. It’s a rather old language and it doesn’t offer very much in the way of features. In fact, compared to Ruby, it’s downright bare. It clearly falls in the realm of system programmers and hardware wizards, both places where a Ruby programmer isn’t exactly a common sight. Why do you, a Ruby programmer, need to learn C?
To the outsider, programming in C seems to be a chore. There are many details about your Code you need to keep track of. And C doesn’t even lend you much of a hand when programming. There are no iterators, memory management is done manually, and handling strings correctly is akin to walking through a minefield with a hood over your head. While on fire. And being chased by a pack of wild dogs.
It’s easy to see why people soon went on to create languages that were much nicer to program in. And it’s hard to see why you would want to write code in it.
Well, for one, C hands you the key to a wealth of libraries that are all accessible from C, even if they aren’t written in it. C has sort of established itself as the lingua franca between languages. When you call OCaml from Ruby (or vice versa), the bridge is built in C. Even Java and .NET offer a C interface, so you can communicate with all those other languages and libraries. And yes, the ‘dl’ library allows you to call C from Ruby, but what if you need to provide a callback function? Then you’re stuck, unless you know C (or you know someone who knows C).
Consider, for example, How I stopped worrying and learned to love errno.h by aredriel. If you were to hit this problem, would you be able to modify the sqlite3-ruby gem to include the errno into the exception? For that matter, do you even know what errno is? Having some C experience allows you to diagnose such problems easier.
But there is a second, more important, reason why you want to learn C.
When it comes down to their basic architecture, pretty much every computer sold today is based on the Von Neumann architecture. It has been improved and modified since its invention in the 50s, but the core attributes are still present. And every assembler language used to control those computers is highly adapted to it. Therefore, if you learn and program in an assembler language, you’re very much aware of how the hardware underneath it operates. You’re aware of every nuance and peculiarity it exhibits, you know what is going on underneath. This enables you to write highly efficient implementations for that computer.
The thing is though, computer architectures come and go, and with them, their assembler languages go out of fashion, and new ones are introduced (like the recent switch from PowerPC to the x86 architecture by Apple). To avoid having to port code and programs from one assembler to another, Dennis Ritchie invented what would later be known C. It is in its very essence just a thin layer over assembler language - thick enough that you can port code written in C to another computer without much fuss, but still thin enough that the hardware and the raw power it provides is at your very fingertips.
A classic example would be sorting algorithms. The fastest implementations of Quicksort are all either in C or assembler. Other implementations in other languages might be far easier to understand, but if you’re sorting an array with a few billion entries, clarity of code isn’t what you’re looking for. And it’s not only sorting algorithms, many algorithms, especially mathematical operations (like matrix multiplication) can be made to perform much better because of what C allows you to do.
Or take memory management. If you think that automatic memory management is always superior to manual management, you’d be mistaken. While it’s true that using a garbage collector is almost always less error prone than manual heap management, you also forego any possible benefits like memory pools or static allocation that can vastly improve the performance of your program.
Computer graphics is one of the few branches of computer science where performance is still very important, and many programs are still written in C or a C-based language (often C++). This is slowly beginning to change as computers are only now getting fast enough to allow programs like Processing (which is written in Java), but it will take a very long time before C is going to disappear completely.
And all this is what makes C worth knowing. It represents the very Von Neumann architecture your computer runs on. Understanding C means understanding what goes on inside your machine. It means you can now rewrite that performance bottleneck in your Code that you simply can’t get any faster in pure Ruby (remember, look for better algorithms first before resorting to anything else). You can now dive into the guts of MRI and at least have a fighting chance to understand what’s going on.
You’ll also know what it means to program with hardly any safety nets. No garbage collector to clean up any stray blocks of memory that you forgot to free, no virtual machine that checks your every step and makes sure you don’t fall of a cliff.
Are you going to need C in your day to day life as a Ruby programmer? No. But every once in a while a problem will pop up where knowing C will allow you to solve it better or faster than you otherwise could have. Knowing C gives you another option when faced in a problem that allows you to explore paths that are very different from what languages like Ruby make possible, especially when it is as easy to combine these languages in one program (Ruby’s C extension mechanism makes it reasonably easy).
And that is why you need to learn C.