For the first time in almost a year, I brushed up on my C fundamentals and built a few toy programs. As I played around with pointers and printed out a memory location, I experienced a literal chill down my spine. I had almost forgotten how marvelous programming in this language was.
The last time I had coded anything substantive in C was almost two years ago, when I had written a Web Server for Professor Jae’s (in)famous system programming class. As a callow junior, I was baptised into a highly partisan cult of C and Unix worship, and I loved every second of it. Well, any second that didn’t involve string manipulation.
In the years since, I coded less and less in C and more and more in languages like Javascript and Python. I had become estranged from low-level systems stuff. Returning to C reminded me why so many programmers love this language.
C is closest to the real
Computer Science traffics in abstractions. As a dicipline, many of its most import conceits were theorized and proven before the existence of physical computers. Modern CS and Software Engineering retains this theoretic and abstracted quality, especially as one employs higher level languages and technologies. Almost by necessity, most programmers have a superficial conception of the vast, layered ediface of systems that enable and support their work. There isn’t anything wrong with this; abstraction is pleasurable and useful in and of itself. But there is also a pleasure to be had in being close to the metal.
When I saw a memory address outputted to stdout, I felt that I was as close to the hardware that I could be without literally opening up my machine and stroking my ram modules like a crazy person. Now I did this in a Ubuntu WSL instance, so who knows what interfaces actually mediated my encounter with a memory address. The point is that aside from assembly, C gets as close as possible to the physical, tangible and real aspects of computing. There is something intoxicating in this proximity to physical components. Your virtual objects, of dubious ontology, suddenly seem as real as your motherboard.
I hope that it is clear that what I am describing is fundamentally a feeling, and is as such highly subjective and is also not morally superior to any other preference. There are a lot of holes in this notion of C being “close to reality.” But it feels that way, and in articulating this, I hope I am able to explain some of the psychological appeal of lower level programming in C.
C as the Ur-language
There is another thing I love about programming in C. Because C endows a programmer with a profound degree of control over memory, you know that it is a very good choice (from the perspective of performance) for building other elemental software. C is often the language of choice for OS, language and systems development. You know you could, at least in theory, write almost everything that could be written in C - from the kernel at the bottom of your OS to the graphics library at the top. There is an immense sense of possibility here. It doesn’t actually matter if you never write a kernel module or a compiler; just knowing you could is often enough to entice you into the cult of C.
Conclusions
In writing this article, I am not making a partisan case for the superiority of C. Rust and other languages are rightfully questioning the propriety of C in relation to its now (in)famous memory safety, or rather lack of memory safety. Python is my other favorite language. But C will always retain a certain mystical quality in my eyes because of what I have described above. I hope I have helped decode the immense appeal of this language, born out of Bell Labs, as our dicipline hurtles away from the bare-metal physicality of lower-level computing.