Channels ▼
RSS

C/C++

Why Code in C Anymore?


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.

More Insights

White Papers

More >>

Reports

More >>

Webcasts

More >>

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.

— Andrew Binstock
Editor in Chief
alb@drdobbs.com
Twitter: platypusguy


Related Reading






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Comments:

ubm_techweb_disqus_sso_-3c296f56913d7a0f191cdcf2371d3742
2014-08-04T05:23:06

"Syntactically and semantically there are a very limited number of ways to do things in C compared to C++." I have theorized for awhile that this is one of the reasons some open-source projects are implemented in C: the "leaders" of said projects don't have to enforce a (C++) coding standard.

By definition there is a limit to how far afield a person can go with C, whereas with C++ there is no known limit to how far a person can go into unmaintainably obfuscated multiparadigm abstractions.


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:55:36

look at LLVM, Clang


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:46:56

is that even C?
btw there is C11 not only C++11.


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:46:18

frankly the only place I will advocate any C related is calling OS API, as people pointed, due to no alternative really :)))


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:45:01

one benefit over broken C# is indeed you can abstract from OO and have a good old plain simple function!


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:43:52

maan just avoid using CPU all together and jump on the ladder diagrams :)))))


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:43:11

ehh, everyone loves to write C till the first moment needs to manipulate such a magick as strings :)))


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:42:08

nightmare^2


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:41:22

I agree. people largely live in misconceptions. like using new and delete :))) where in practice using c++11 those two should be used exactly 0% of the time


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:39:44

well guess what, C is just a tiny portion of C++ as C is subset of C++ with maybe 0.1% difference.
C is clear? which C? let me guess the one you write :)))


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:37:55

"Then again, I like to write code generators that spew out most of the "grunt" code so that I can focus on the actual problem I'm attempting to solve, so my perspective is likely a bit skewed."
nice! people tend to forget about that option!


Permalink
ubm_techweb_disqus_sso_-cdc38e95e93ee974012b13314fff4eef
2014-02-04T15:36:41

keep up to date. more than half is simply not true. C++ is still a hodge-podge of not very well assembled bits and pieces." and C is still the language which has now idea how big (limts) of its arrays is !


Permalink
ubm_techweb_disqus_sso_-41e3a1996a764660c5eda9c53e7ceedb
2013-06-26T14:05:19

Which you would have to some how enforce the use of in place of a simple 'return' statement, and the code at the goto label would have to be able to safely handle a return from any point in the function from which it was called.


Permalink

2013-04-25T19:46:51

Or you could just use a simple 'goto'


Permalink
rudmerriam
2013-03-20T18:33:37

In the early 90s for Embedded Systems I did a benchmark comparison for C/C++ on using polymorphism through virtual functions. The result: virtually no difference in the timing when implementing the equivalent programs. The problem with comparing the languages is you have to make sure you are comparing apples to apples. You cannot write a C program using one approach and a C++ version using a different approach and say they are the same.

The benchmark I did said the equivalent of virtual functions in C is using a switch statement. This was actually slower by a trivial amount than virtual functions! This was especially true if encapsulated in a function as it should be following structured programming guidelines.

Did you know that using STL for_each is faster than a for loop? At least it is with my MS compiler.

The C++ compiler in most case is the C compiler with the additional C++ constructs added in. For any constructs that are the same the machine code is going to be the same. How can that lead to slower run times when probably 80% of the code is not specific to C++?

I don't have time right now to dig into why the benchmarks are showing such a difference. A quick look at couple months ago when this came showed that the programs were not really equivalent structurally. Which is my point in the first paragraph. They are just programs written by different people to solve the same problem. That is not a valid comparison.


Permalink
ubm_techweb_disqus_sso_-6489bc08bbe3f009e56e2326d834d6e2
2013-03-13T16:22:11

I totally agree. Another point that seems to be overlooked in this comparison is that it is quite easy to use both languages within the same program. I am an advocate of using C++ for user-facing i/o and C for core logic. This avoids templates, inheritance, etc. that make the core logic harder to understand, while avoiding the string overrun issues that I see as the C library's most glaring issue.


Permalink
ubm_techweb_disqus_sso_-8e26fb82becb4c33dc8b5acb5b2dc2c9
2013-03-08T16:21:36

6 years ago the project was renamed, and the name has not changed since.

http://benchmarksgame.alioth.d...

Google's webmaster tools "Search Queries" analysis tells me hardly anyone uses "alioth" as a keyword to find the website.

Don't promote worse -- promote better.


Permalink
ubm_techweb_disqus_sso_-f9d132c695f2caac31546891b8badc15
2013-03-08T14:29:42

Believable aspect! And new for me at least. Somehow characterizes the nature of C++.


Permalink
ubm_techweb_disqus_sso_-03f7cfc46738ae7a778b5405aec93d12
2013-03-07T00:27:44

Can you please explain why would you need to look at the generated machine code? With a debug build you can easily correlate source code lines with the generated machine and assembly code.

Release and debug builds should functionally be the same, as this is one of the compiler promises.


Permalink
ubm_techweb_disqus_sso_-918bac0287dc24a6ba5bee26ad7f5ac3
2013-03-06T17:31:26

Another situation when C should be chosen over C++ is when you have to look at the generated assembly code. Its much harder to map the C++ code with the generated assembly.


Permalink
ubm_techweb_disqus_sso_-8e26fb82becb4c33dc8b5acb5b2dc2c9
2013-03-04T20:31:50

@zahirtezcan -- If you want to see C# programs that use structs for generic containers, write those programs and contribute them to the benchmarks game!


Permalink
ubm_techweb_disqus_sso_-b34dd0c828a2311fbf333e1e4da13c40
2013-03-03T15:57:52

Are those benchmark examples carefully engineered? I know issues about C# examples there, that they don't use structs for generic containers under the assumption of Java-generics. C# generics are highly optimized w.r.t. java ones. What I mean is there might be issues about C++ code too. because 27% is really high if you think about what you can do with c++ (e.g. c++ std::sort(...) vs. C qsort(...) )


Permalink
ubm_techweb_disqus_sso_-77616294493a025bef82af1bd131b649
2013-03-03T11:25:42

Hmm, these benchmarks really compare apples and oranges.The only performance question answered is "Does abstraction cost some performace?", and the answer is unsurprisingly yes. It's about as useful as comparing assembler and C. You loose some performance and gain some abstraction, but you can always mix. Even if you choose not to go all out OO, you can still write better C-style code using a C++ compiler because you can use the RAII idiom for resource management and other benefits


Permalink
ubm_techweb_disqus_sso_-16a1458b81f95f25c013ac0d08842c1f
2013-03-02T05:58:32

Good article. Although C++ has inherited many of its aspects from C and C++ is a bigger language than C, C is still the first choice of programmers to develop system programs.


Permalink
ubm_techweb_disqus_sso_-03f7cfc46738ae7a778b5405aec93d12
2013-03-01T21:01:19

If you want to keep using older compilers, you'll lose the benefits of C++11, which is being gradually implemented into compilers. If you use compilers from different vendors (VS/clang/gcc), then you'll also lose C++11 functionality, since you'll have to target only the common subset, implemented in all of them.

ABI depends on the OS. WinRT is a good model for ABI, but it's only available on VS 2012 on Windows 8 / WS 2012. On the positive side, you can use WinRT functionality outside of Metro.

With C++/CX (or C++ and libraries) you can expose certain public WinRT types, which are consumable from other WinRT applications.

Personally, I think this is the way to go: not simple C++ interoperability between compilers, but ABI compatibility with any programming language that supports it. Conceptually it is similar to .NET types - they are public types, consumable from other applications, while your internal types stay as C++ (STL) types.

Now, if you don't ship libraries as binaries, available to 3rd party developers, then standardizing on the latest compiler is your easiest and most productive option (C++11 etc).


Permalink

Video