Why do we still use C?

[slightly edited from a private flame yesterday]

If you have ACM access to the PLOS 2006 proceedings, I recommend Jonathon Shapiro’s paper _Programming Language Challenges in System Codes_ (Why Systems Programmers Still Use C, and What To Do About It) — it doesn’t appear to be reprinted anywhere else, so I’ll snip a bit of it:

Systems Programming . . . [is] fundamentally about engineering rather than programming languages.  In the 1980s . . . engineering considerations were required criteria for language and compiler design.  By the time I left the PL community in 1990, respect for engineering and pragmatics was fast fading, and today it is all but gone.  The concrete syntax of Standard ML and Haskell are every bit as bad as C++.  It is a curious measure of the programming language community that nobody cares. 

He gives some examples, notably a TCP stack in SML that, while a notable achievement, is at best 11 times slower than the native stack on the same architecture (and worst case performance is unbelievably miserable).  He makes a point that going from a factor of 1.5 to 2 in performance is not negligible when this translates directly to the number of servers that you have to buy, power, cool and maintain.

Frankly, I’m sick of C (and the safe subsets of C++ that are basically sugared C), but it’s the only damned tool around that will do the job.  Pick another language that you can reasonably implement an OS in, what are the choices?  Oberon, Modula, extended Pascal . . . Ada, BLISS?  These are all essentially the same animal with their semicolons in different places.  Java, C#?  No resources on the platform for these.  LISP?  Worse and worse.

On something new: I don’t have time to get a PhD in type systems.  I need a debugger that works.  I still need to write assembly language and really worry about the number of cycles involved in some operations.  But I’m tired of writing bugs and races and want something lots *safer* than C, and everything out there now is mired in a decade of theory that doesn’t help systems programming at all; even if I spent the time to learn and move in with it, it wouldn’t help.

Shapiro’s solution (BitCC) is interesting.  I won’t go into it here.

Someone I read recently had the idea of putting the whitespace and formatting into the grammar; like Python (say), but with no semantics (e.g., no indentation-equals-a-scope), only checking.  At least you avoid “one-true-brace-style” wars that way.  But this is the least of our problems.

Maybe if we took away these PL theorists’ Emacs and LaTeX packages for a while we’d get better results.  Threaten to take away their fast TCP stacks and graphical interfaces.  It’s time for the programming language community to do something for the systems programming people, something that actually works well on bare metal.

This entry was posted in Rantage. Bookmark the permalink.

13 Responses to Why do we still use C?

  1. Allen says:

    BitCC was the first thing that came to mind when I saw the title of this post. How about you go into it?

  2. Tim Locke says:

    What do you think of Digital Mars’ D?

    http://www.digitalmars.com/d/

    It is a lot safer than C, allows assembly language, runs as fast as C, has optional garbage collection. In my mind, it is what C++ should have been but could not have been without sacrificing backward compatibility, which D does.

  3. Uzair says:

    Have you looked at D? It’s certainly from the C family but much cleaner than C++ ever dreamt of being.

  4. Eli Gottlieb says:

    Try out Object Pascal, as implemented by the Free Pascal Compiler. It’s got classes, manually allocated dynamic arrays, reference counted strings that can be handled manually at the programmer’s convenience, a much stronger type system than C, exceptions, and the option to compile in run-time sanity checks.

    The only downside is that you have to write a minimal Run-Time Library for bare metal. I can send you mine, if you like, but several are already on the Free Pascal unit contributions page.

  5. CLH says:

    The Lisp Machines ran an OS written in lisp, hardware designed specifically to run Pascal, and even Java bytecode. Naturally the LMs had an emacs-like editor, zmacs written in lisp along with the GUI, TCP/IP stack, etc.

    C is used for those purposes today because the OS and libraries they run on are written in C, and because hardware is optimized for C’s execution model, not because of any inherent superiority for such tasks.

  6. landon says:

    I looked at D. It doesn’t truly change anything about the way you do systems software (that is: Pray that you have everything compiled in sync with the same headers, with nothing stale, that you understand the memory system semantics, that the fancy runtime hasn’t gotten in your way, and that you haven’t forgotten a zillion rules for environment you’re writing for).

    I have a rant in progress about this….

    Oh boy.  In the early 80s I was in love with LISP machines (made a pilgrammage to MIT to visit my friend Jack and to see the LMs on the 9th floor). Wonderful things, but evolutionary Do-do birds as soon as stock hardware got fast enough (I’m going to have to crank up a CADR emulator some time).

    I’ve written tons of code in Object Pascal. Thanks, no. This was in the late 80s and early 90s on the Macintosh. My experience with Pascal-like languages is that you generally lie to the type system about as much as you lie in C.  The languages are really equivalent.  You’re doing the same things, with “semicolons in different places.” I believe that Object Pascal has non-“duck”-types, which are stronger, yes, but I think not the whole story.  Again, things like having stale objects around, getting interfaces out of sync and screwing up your environmental rules are equally possible. O-P is not a panacea.

    More, when the toddler is asleep… 🙂

  7. Eli Gottlieb says:

    “Pray that you have everything right in sync, that you understand the memory system semantics, that the fancy runtime hasn’t gotten in your way, and that you haven’t forgotten a zillion details about the rules for environment you’re writing for).”

    In that case you need a language whose syntax, semantics and runtime all match the architecture to which you code.

    I’ve got a pet kernel whose virtual memory manager has had too many bugs for ages, so I’d love a language that inherently understood what page tables, segments and descriptor tables are, and how to check them for validity! However, this language would be stuck firmly on my x86 processor. It would limit the portability of my kernel in addition to its own. Yikes.

    We use C and Object Pascal as compromises: low-level enough that a smart human can take the time and write useful systems code without the language’s ideas about theory of computation getting in the way, but high enough that doing so takes months instead of years.

    A Lisp operating system worked on Lisp machines where the language matched the architecture. C still reasonably approximates the resources available to a kernel programmer at boot when the kernel knows nothing about the hardware it runs on and has no hardware resources of which to speak.

  8. Joshua Volz says:

    Wasn’t C supposed to be the “portable assembly language?” I believe that C’s flexibility to work on multiple architectures has helped its proliferation. It’s also the beginning of everything. There aren’t language replacing it, because most of the languages that have been written since then are implemented in C or C++. Java, Python, Ruby and C# for example.

    Admittedly, C doesn’t provide the higher level abstractions and doesn’t really supply a way to create domain specific languages with ease (for example, somebody mentioned the language understanding paging above). If you need to create a DSL, you are basically as restricted as you are in Java, which leads to fooling the type system (void* anyone) or making a bunch of XML documents.

    I think we still use C because we have a large amount of existing C code, it’s really fast (particularly compared to the languages implemented in it), everybody who learned CS in school is at some point forced to learn about pointers, as they are the basis for all kinds of other artifacts in the higher level languages. This is kind of like asking “why do we still use gasoline?” The answer is that everybody is used to it, consumers, mechanics, car companies, oil companies, national politics, et cetera. If you make a fundamental system change, everyone will have to be reeducated. I am not saying it is impossible, I am just saying it is a big task.

  9. Tim D says:

    What do you think of Forth? It’s different and it’s fast.

  10. landon says:

    (See post about FORTH).

  11. Jason says:

    C is also hard to leave. I come from a kernel background on embedded applications. Now I’m designing a server, and performance is key. I find it hard to trust languages such as Java in terms of memory allocation, efficient buffer handling, etc. Everything tells me to use C, but we’ll be hiring other developers over time that probably won’t be C experts, which scares me into using something a little more application programmer friendly.

  12. Jack P. says:

    C is so close to current CPU hardware that I don’t see how another language could get “under” it to force it out of the system programming niche. At best we might see some upwards compatible extension (e.g. GNU C, or C 9x or C++) become popular enough to effectively replace C, just as ANSI C has effectively replaced the original K &R C dialect.

    Also, I don’t think we’re going to see any new CPU architectures (x86 or Arm) or OSs being developed, and all major current OSs (Unix, Windows) have a C-based API. So C will probably always be the first class citizen for OS work. (Where always means at least 20 more years. 🙂 )

    But C has clearly lost ground in the application programming space, where VB/Java/C# rule, and in the client side of web apps, where JavaScript rules. (And if you consider C-based system programming error prone, wait until you try developing AJAX/ATLAS style programs!)

    P.S. I am interested in some of these wacky French programmed-proof systems, like the verifiably correct C compiler that the Coq project is working on. I would like to have a compiler that was known to be correct. If only it didn’t typically take eight times as much code to prove a system correct as to write the system in the first place.

Leave a Reply

Your email address will not be published. Required fields are marked *