A long-time reader of Dr. Dobb's recently asked me why anyone would code in C anymore. This theme has lately appeared in some comments posted on our site, and earlier in several conversations with industry figures, particularly at Microsoft. In the early days of C++, there were many reasons to choose either C or C++ depending on your needs; but as C++ has evolved, a lot of the traditional distinguishing traits of C have indeed become less advantageous. Because these points are generally the first to appear in any comparison of the two languages, let's examine them.
White PapersMore >>
- Enabling a Smooth DX Transformation in the Post-Pandemic New Tomorrow
- Thinking Like an Attacker: Strategies for Defense
Performance. It used to be true that C++ was considerably slower than C. But on most major platforms, the difference in performance today is small. The computer benchmarks hosted on Alioth, for example, show that C++ (running on 32-bit Linux) runs the series of tests 27% slower than C. Other surveys show this difference as slightly larger or slightly smaller. But in almost all cases, C++ is the next fastest language after C. It is generally much faster than JVM and .NET hosted languages. So, while C retains an advantage in benchmarks, in most apps that would accept Java performance (so, any enterprise apps or client-facing software), the difference is not substantial.
Ubiquity. In the embedded programming world, where C is still happily ensconced as the primary language, it is preferred due to the fact that every hardware vendor offers a C compiler. It used to be true that C++ did not figure strongly in embedded development. However, today most component vendors who offer programming tools offer a C++ compiler. (The consistent exception is in PIC microcontrollers.) This is a dwindling benefit.
Portability. C++ used to be a dog to port. (Actually, C was, too, before the C89 standard.) However, compilers nowadays have implemented the core of the C++ language sufficiently that most software can be recompiled with few, if any, tweaks, provided the code is written, as Brian Kernighan once put it, "down the middle of the language." Library portability presents a more troublesome factor, but the same problem exists with C libraries. In both C and C++, standards compliance of compilers varies tremendously, so using features that are not fully supported (C99 and C11, C++11) is an equally inherent risk. That being said, C89 is probably the most portable code in the world. (And for this reason, it's chosen where portability is an overriding concern. For example, the Lua team chose C for this reason as well as its performance.)
It is fair to say that for performance, ubiquity, and portability, C still has advantages over C++, but that those advantages are steadily diminishing. In this regard, the C++ community has done well by its users to address what were once substantial obstacles to adoption. The question is: Do those shrinking advantages offset the benefits of C++? These include object orientation, exception handling, better type management, templates, larger standard libraries, and so on. Without those benefits, every project in C can feel like trying to mow the lawn with a pair of scissors.
Those features certainly help getting the code written, but they have a cost complexity which is where C most readily distinguishes itself from C++. C is one of the few general programming languages that is small and simple enough that you can get your arms entirely around it. It is indeed possible to know the ins and outs of the language completely, as well as knowing the standard library well enough to use it without having to look up an API call. I don't believe this is possible in any other major language, certainly not C++.
This smallness is one of the language's attractions. You can learn it quickly and be productive fast. This simplicity is enhanced by another rarely discussed characteristic: the supreme legibility of the language. I mean this semantically in addition to syntactically. Semantically, there are a very limited number of ways to do things in C. Consequently, when you read the code anyone's code you know exactly what they're doing. C++, by contrast, has many different ways to do the same thing a flexibility that its developers enjoy. Because of C's clarity in this respect, it is an excellent language for writing complex infrastructure. For this reason, the original writers of the JRockit JVM (now, Oracle's primary JVM) chose C. In conversations a few years ago, they articulated their view that by choosing C, and not C++, they could onboard developers more quickly; and when doing deep dives into the code, they could understand what they were looking at much more easily than in C++.
For this alone, C remains an excellent choice for systems-level code: It's fast, it's portable, it's easy to read and understand. For applications, though, where the emphasis is more on development productivity, it's clear that C++ will continue to dominate native languages and likely expand its footprint.