I have something to admit. I love C. I've known it for a while, but it's easy to forget. I've gone away to Ruby, Haskell, OCaml, C++, Java, and C# - I spend time with many languages, but when I go back to C, it's like coming home.
I remember flipping through the Kernighan and Ritchie book decades ago, trying to pick up the language. I remember a lot of frustration, but I also remember a lot of satisfaction. C has its quirks, but in retrospect, they are a lot less mysterious than the quirks of many other languages. They don't require deep reasoning. The behavior of a construct is either defined or it isn't, and since undefined behavior has such a high cost, people are careful. They have to be.
A friend of mine, Kevlin Henney, talks quite a bit about affordances in software. An affordance is, essentially, the envelope of perceived action possibilities that a thing offers. People often think about this in terms of "what the software allows you to do" but I think there is a more expansive way of looking at this that explains C. C is prickly, so its affordance is care. If you don't approach your C code with care, you're dead in the water. C's conceptual simplicity and its prickliness are a powerful combination.
Another nice thing about C, from my perspective, is recovery. I don't like repeating this over and over, but I think it gives a bit of perspective to say that I spend most of my time visiting extremely ugly code bases and helping people get past issues in them, and of all of the languages that I frequently encounter code in, the one which is hardest to recover in is C++. There are quite a few reasons, and I won't go into them here but, really, at certain point in a degenerated C++ code base, the language is actively fighting you. I can't count the number of dependency nightmares I've seen - systems where any attempt at a build takes any insane amount of time - where the cure is at least as painful as the path to disease. C, on the other hand, seems to be more recoverable. Or, maybe I've just been lucky.
The problem with C++ (and it's not unique to C++ by any means) is that it tried hard to make things better within an existing framework rather than jumping into a new one. It tried to tune toward better and often that is a disaster. Yet we keep trying. We try to mutate languages like Java and C# into things that they aren't - and, without knowledge or respect for what is there, we fail.
There's something deep in software development that not everyone gets but the people at Bell Labs certainly did. It's an undercurrent of "the New Jersey Style", "Worse is Better", and "the Unix philosophy" - and it's not just a feature of Bell Labs software either. You see it in the original Ethernet specification where packet collision was considered normal.. and the same sort of idea is in the internet protocol. It's deep awareness of design ramification - a willingness to live with a little less to avoid the bigger mess, and a willingness to see elegance in the real rather than the vision.
I was reading a magazine article a few weeks ago whose author implied that the designers of the internet had just stumbled across an approach that embodied sound systems design principles. It really bothered me. I wanted to throw the article across the room. No, those guys knew. They had deep systems thinking skills and they acquired them the hard way. That sort of design only happens when you reflect deeply on a problem and figure out how to work with its grain. C is a language that works with a grain.
I've never met Dennis Ritchie, Doug McIlroy, Ken Thompson, or any of the other pioneers but my impression from afar is that they didn't believe in the perfectibility of man or software - they were beyond that trap. They saw limitations and they worked with them - they didn't over extend.
The fact that C embodies that style, is one of the things that makes it special to me. It's a style that deserves more recognition and emulation.

Comments (21)
It's interesting that you advocate worse-is-better and yet dump on C++. C++ was successful because it followed worse-is-better. Objective C took a clean-slate approach and never took off. The "portability" that the original worse-is-better paper refers to is exactly what allowed C++ to spread so quickly. (Portability of implementation, reuse of existing C syntax and concepts, etc.)
Posted by Lawrence Kesteloot | January 27, 2008 9:06 PM
Lawrence: I wasn't dumping on it. I still love the language, but it is my experience that it is harder to recover in than any of the other mainstream languages. The only one that's been worse in my experience is reference-counted Delphi.
Re Worse is Better, simplicity is part of the Worse is Better style (notably simplicity of implementation over simplicity of interface), and I don't think that C++ can be categorized as simple in either interface or implementation. It did spread widely but really on the back of C.
I think that Gabriel's argument in Lisp: Good News, Bad News, How to Win Big is more about survival than initial spread and although I don't think C++ is going away, I do think that C has the edge on survivability both because of its influence and because of people's dogged persistence in using it instead of C++ for various domains.
Posted by Michael Feathers | January 27, 2008 9:45 PM
"It tried to tune toward better and often that is a disaster."
You almost make feel that C++ tried to do something and did not succeed at all. The beauty of C++ is most appreciated by people who know C well and have faced problems developing big enterprise wide software solutions, where manageability was an issue -- manageability both in terms of team size, code churn, design and modularity. In my limited experience C++ is the only high level language that lets you design your software that simulate real life situations, yet keep the developers very close to the hardware(system resources) they are working on. It allows you to think one problem at a time, unlike C. In C, you most of the time need command on the entire problem even for a simple bug fix because of its non-object oriented nature---and there is a reason for it --it was not meant to be OO. Other languages like Java or the .Net family to me are tools that a carpenter uses to get some job done --- not taking away all the pros that these languages have to offer.
Posted by Shuva | January 27, 2008 11:25 PM
Bravo, sir. Bravo.
Posted by Nick | January 28, 2008 12:45 AM
Shuva: I'm not trying to be trite but operating systems are big. They have all the issues you mention, and yet they seem to do well in C.
Again, my issue isn't with C++ as much as it is with the mutation of C into C++, or the mutation of Java into Java with generics and closures. There's a point at which you have to respect the limitations of your base and choose a new one.
Posted by Michael Feathers | January 28, 2008 1:46 AM
Re. Shuva's comment.
I think you're right, C++ works well and, I think if it is very well managed one can minimize recovery issues.
However, likewise, a very well managed C project can enjoy the modularity of a C++ project. Like you said it's not designed to be OO, and you should bother to imitate OO, THEN you might as well use C++. But OO and modularity are not 1-1.
That said, in either case the KEY is a really good design and plan.
Posted by Joe | January 28, 2008 1:59 AM
I think old people love C.
New people love languages where they can do more in less time. Like Ruby ;-)
But I agree insofar that there is no way _around_ C.
I just disagree on the "love" part. C is practical, but love ...
Posted by she | January 28, 2008 6:38 AM
"There's a point at which you have to respect the limitations of your base and choose a new one."
Would you say that programming in a functional style in C++ via templates and metaprogramming would fall into this category?
Posted by Martin | January 28, 2008 8:34 AM
Have you looked at D? What do you think of it?
Posted by Reedo | January 28, 2008 9:36 AM
C also occupies that one-step-above assembler niche perfectly.
Where C++ and Java and still fighting over the OO niche, and Perl, Python, and Ruby are fighting over the interpreted language niche, C simply has no competitors. It does what it has to do as perfectly as it possibly can.
Posted by Justin | January 28, 2008 9:51 AM
If you love C, you should also check out Objective-C, which is a superset of C with a simple extension for supporting high level OOP. You get the best of the two world -- the beauty of hard wired low level C programming language and an elegant layer of modern high level OO abstraction.
Posted by Simon Pang | January 28, 2008 10:45 AM
Great article, thanks much.
Posted by Sam Jones | January 28, 2008 10:55 AM
This was an interesting article to read, mostly because I've been hating C lately. The biggest reason is that I think exceptions are completely necessary. But I can also see all of the problems with hidden resource cleanups that exceptions require.
Don't get me wrong, I completely hate c++ too. I think it's really weird and has a lot of quirks that must be understood and handled carefully. However, I think the fact that it has exceptions makes it much more useful.
I'm also curious what you think of D. You should make a post on it. I feel like it's a modern version of what c++ should have been.
Posted by brain | January 28, 2008 11:39 AM
I love C. I hate C++ and refuse to work with it -- the goal for C++ was object orientation, and back then I understand it was a difficult thing to patch on to C. If you really want object-oriented C, use Objective-C -- it is a clean superset of C that is as easy to understand and read, and in your terms, easily 'recoverable'.
/s.
Posted by Scott G | January 28, 2008 9:09 PM
Yer right, Man. I love C.
Posted by Jim | January 29, 2008 10:49 AM
"and of all of the languages that I frequently encounter code in, the one which is hardest to recover in is C++."
I agree with you up to a point. Mostly it's programmers who write the "bad" code that makes any language difficult.
"Old people love C", well then I'm real old :-)
I've used so many languages C++, C#, modula 2 etc but I certainly love C.
As far as C and OO, take a look at Programming with Objects in C and C++ , Allen I. Holub.
Posted by David Camacho | January 30, 2008 2:09 PM
C is definitely not just for older programmers. I'm 24 and C is like my mother tongue. When I was 16 my parents bought me my first computer. The first thing I did was install some games :) The second thing I did was to try and figure out how those games were created, so I could create my own. At the time I was addicted to "Rogue-like" games, esp. ADOM, Angband & NetHack and these were/are all written in C. I never did write any games, but that's how I discovered C. I now use C# at my day job, but I still sometimes steal a couple of hours from my employer to write a few lines of C.
Writing C code _does_ require great effort and care, but it's also a deeply rewarding experience. I liken it to being an amateur mechanic: it costs precious time to maintain your vehicle, but it can also be very satisfying.
Posted by Ralph Moritz | January 30, 2008 3:05 PM
I love simplicity and cleanliness, so I love C too.
Posted by Kevin Rutherford | January 31, 2008 3:50 PM
Just to take operating system written in C++ argument a bit further; BeOS was as far as I understand it written in C++, and from the developer's point of view this made it a dream to code for as most system objects were exactly that - first class C++ objects. Oh and it was very fast. I am biased - my day job is 90% C++ - but I do wander why in this day and age so much of linux is written in C, not C++. I appreciate that my opinion is based on the way I personally code and think about software design, but I know how much harder my job would be if I only had C++--.
Posted by James Thompson | February 2, 2008 3:16 PM
Michael what a joy to read your article. Your words bring me the courage to say it ...my name is susan, and I love C ... So sad that this is considered an antiquated tool. Yes java is great...but I really do miss the elegance of pointers.
Posted by Susan Harriman | February 2, 2008 4:01 PM
I feel ya brotha... C is wonderful... I too am a new developer, (graduated almost 2 year ago) .. I work with many languages, C, C++, java, etc.. I work on an older system that was designed when i was 12 years old... it is written in C.. The designers and maintainers did a wonderful job with the code.. It's thousands and thousands of lines of code... its easy to read.. easy to follow... it's simple(yet complex).. and it's fast..
-BJ
ps
(linux developers write in C because they are smart)
Posted by bj | February 3, 2008 2:34 AM