Why does C still exist, when C++ can do everything C can?

This was a question asked on Quora and the top voted answer was airing on the side of it being cultural or personal preference. I don’t think the answer is culture or preference; there is an excellent reason why both C and C++ exist today. C++ is not a good alternative to C in some particular circumstances.

Many people suggest that C++ generates more inefficient code, that’s not true unless you use the advanced features of the language. C++ is generally less popular for embedded systems such as microcontrollers because its code generation is far less predictable at the machine-code level, primarily due to the compiler optimizations. The smaller and more resource-limited the target system, the more likely that C is a better and more comfortable choice for the developer, and this is often the reason people suggest that C++ can not replace C, and that is a very good reason indeed.

However, there’s another even more fundamental reason that C remains a critical tool in our armory. Imagine you create your very own new CPU or computing architecture for which there is no C or C++ compiler available to you – what do you do? The only option you have is to write code using some form of assembly language, just as we did in the early ’80s when programming IBM PC’s and DOS, before even C, became mainstream. (yes there was a time when C was more obscure than x86 assembly!) Now imagine trying to implement a c++17 standards-compliant C++ compiler and STL library in assembly language, that would be a daunting, and unimaginable task for an organization of any size, right?

On the other hand, a C compiler and a standard C runtime library, while still not an insignificant effort, is a hell of a lot more achievable, even by a single developer. In truth, you would almost certainly want to write some form of assembler/linker first to make writing the C compiler simpler. Once you have a standards-compliant C compiler working well enough, then a vast array of libraries and code written in C becomes available, and you build out from there. If your target platform did require a c++17 standards compliance c++ compiler, you would write that in C.

The C language holds quite a unique position (possibly only comparable to early Pascal implementations) in our computer engineering toolbox, its so low level, you can almost visualize the assembly code that it generates, just by reading your C code which is why it lends its self so well to embedded software development. Despite this though, C remains high-level enough to facilitate the building of higher-level application program logic and quite complex applications. Brand new C++ compilers would most likely get written in C, at least for early iterations, you can think of C as an ideal bootstrap for more significant and more comprehensive programs like an operating system or a C++ compiler/library.

In summary, C has its place, and its hard to see any good reason to create an alternative to C, its stood the test of time, its syntax is the founding father of the top modern-day languages (C++, C#, Java, JavaScript, and numerous others, even Verilog). The C language is not a problem that needs to be solved, and the C language does not need to be replaced either. Like oxygen, C is old hat now, but it works well, and in the world of software development, we still need it.

This content is published under the Attribution-Noncommercial-Share Alike 3.0 Unported license.

6 comments

  1. Well said! It’s hard to imagine a world without C!
    Kind of amazing that I used to develop before then and was in total control of my computer. Where are the days 🙁

  2. Also the C++ ABI is intentionally unstable. C’s ABI is stable. That means that most languages (including C++) use the C ABI for their Foreign Function Interfaces. So if you’re mixing languages you’ll typically end up with C shims in between.

    C has its flaws, and there are often better languages to use for a given application, but there are plenty of cases where C is the best choice, even where newer languages like Rust or C++ can provide similar performance with greatly enhanced safety and usability.

    1. Hi Carl,
      Absolutely, you make a good point about the C ABI, interestingly enough it had to be stable and well-defined for library and operating system development when ASM was still hand-coded – no such requirement for C++.
      Gerry

    2. ABIs are defined in Assembly by OSs, not C language. It did changed to add the __fastcall, so even if it is stable, it could continue to grow. ABIs are compatible with all Compiled Programming Languages, most Interpreted Languages, and most Byte Code/Virtual Machine Languages.

  3. The scenario described in the article is not very realistic today.

    Here’s a realistic one: Implement an LLVM backend for your new CPU architecture and, hey presto, you have a full C++17 compiler for it. Then cross-compile the LLVM toolchain to your new CPU (after you’ve presumably got an OS running on it) and you have a full C/C++ suite to work with, running on your new architecture. Much easier than writing a C compiler from scratch in C++, let alone in assembly.

Leave a Reply to gerrysweeney Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.