163
votes

I've been introduced to Computer Science for a little over a year now, and from my experience it seems that C and C++ are both considered to be "ultrafast" languages, whereas others such as Python and such scripting languages are usually deemed somewhat slower.

But I've also seen many cases where a software project or even a small one would interleave files where a certain number n of those files would be written in C, and a certain number m of those files would be written in C++.

(I also noticed that C++ files almost always have corresponding headers, while C files not so much). But my main point of inquiry is to get a general sense of intuition on when it is appropriate to use C over C++, and when it is better to use C++ over C. Other than the facts that (1) C++ is object-oriented whereas C is not, and (2) the syntaxes are very similar, and C++ was intentionally created to resemble C in many ways, I am not sure what their differences are. It seems to me that they are (almost) perfectly interchangeable in many domains.

So it would be appreciated if someone could clear up the situation! Thanks

14
  • 4
    Using C inline in C++ code is usually for certain modules that need to be highly optimized, do very low-level work closer to the hardware, or are critical for integrity of the data or even human safety and need to be auditable and proven correct. Rather than doing it all in C, the bulk of the project can take advantage of C++ features for flexible designs, while getting the benefits of C's tightness in those places where it is needed.
    – kylben
    Commented Oct 9, 2011 at 18:49
  • 30
    @kylben: Many C++ guys will tell you: (1) Performance is not a reason to drop to C (perhaps to avoid virtual and a few other features which prevent optimizations, but e.g. non-virtual classes aren't inherently inefficient, and templates are a powerful abstraction tool that can actually lead to more efficient - e.g. qsort vs std::sort). (2) High importance of correctness is a reason to use C++ (typesafety, constness, private, RAII to make resource management manageable, etc.) over C. Or for that matter, use Ada or something in the first place.
    – user7043
    Commented Oct 9, 2011 at 20:33
  • 11
    @Pubby8 I disagree with this. If I am working on a .c file and I see people do this, I tend to mentally flag them as not knowing what they're doing. For example, there's no need to cast from void* to another pointer type in C code, it's very distracting and typical of people who don't know C.
    – asveikau
    Commented Oct 10, 2011 at 1:16
  • 4
    @kylben: (You might want to learn to properly address others in your comment replies, so they have a chance to actually see them.) That "a programmer very familiar with how the compiler turns C into asm" would work for C++ just as well. But that's simply irrelevant: If you want to dabble in asm, just write asm instead of having a compiler create it from some other language. The way it does this might change with every compiler update, after all.
    – sbi
    Commented Oct 10, 2011 at 6:36
  • 9
    In my humble opinion... you use C when you want to, for me: C is much more simpler and easier to use than C++ ... C++ might look like a "C With classes", but it's not anymore, now it's a very complex language, with things like Virtual Constructors and Templates. Commented Jun 21, 2012 at 21:02

12 Answers 12

185
votes

You pick C when

  • you need portable assembler (which is what C is, really) for whatever reason,
  • your platform doesn't provide C++ (a C compiler is much easier to implement),
  • you need to interact with other languages that can only interact with C (usually the lowest common denominator on any platform) and your code consists of little more than the interface, not making it worth to lay a C interface over C++ code,
  • you hack in an Open Source project (many of which, for various reasons, stick to C),
  • you don't know C++.

In all other cases you should pick C++.

22
  • 15
    I would also add that C++ with exception model sometimes brings more trouble than it's worth, for say, OS kernels. At least that's the general feeling I have gotten while reading about stuff.
    – Coder
    Commented Oct 10, 2011 at 0:26
  • 12
    @SF: C is the lingua franca? That's new. Or rather, very old. Maybe if you only converse with people who haven't learned new languages for the last 20 years, but I'd say that C knowledge isn't very common anymore.
    – DeadMG
    Commented Oct 10, 2011 at 12:44
  • 13
    @SF.: As I have written elsewhere, I've been in projects that amounted to millions of LoC, and saw very few meta-stuff compared to C projects with their inevitable and ubiquitous macro hackery. (OTOH, the ability to create EDSLs when needed can be an incredibly powerful tool in your box.) As for C being the lingua franca: I'd rather stick to my term that it's the lowest common denominator. And I wouldn't want people with moderate programming skills hacking at an OS kernel.
    – sbi
    Commented Oct 10, 2011 at 12:45
  • 18
    @Max: I completely disagree. C is a useless language, unless some insurmountable practical barrier prevents the use of C++.
    – DeadMG
    Commented Oct 12, 2011 at 15:45
  • 17
    @Buttons: It was you who made a claim ("C++ needs more memory"), so it should be you who backs that up. And, no, I am not claiming that C++ needs less memory. What I'm saying is that features cost, no matter whether the compiler implements them for you (virtual functions) or you do them yourself (array of function pointers).
    – sbi
    Commented Sep 27, 2012 at 9:41
88
votes

There are a few reasons to prefer C. The main one is that it tends to be more difficult to produce truly tiny executables with C++. For really small systems, you're rarely writing a lot of code anyway, and the extra ROM space that would be needed for C++ rather than C can be significant.

I should also add, however, that for really tiny systems, C has problems for exactly the same reason, and assembly language is nearly the only reasonable choice. The range of system sizes within which C really makes sense is quite small, and shrinking constantly (though I'll admit, fairly slowly).

Another time/reason to use C is to provide a set of functions that you can bind to from essentially any other language. You can write these functions in C++ by defining them as extern "C" functions, but doing so restricts those functions to presenting an essentially C-life "face" to the world -- classes, overloaded functions, templates, and member functions, etc., need not apply. This doesn't necessarily restrict development to C though -- it's perfectly reasonable to use any and all manner of C++ features internally, as long as the external interface looks like C.

At the same time, I have to say that @Toll's answers (for one obvious example) have things just about backwards in most respects. Reasonably written C++ will generally be at least as fast as C, and often at least a little faster. Readability is generally much better, if only because you don't get buried in an avalanche of all the code for even the most trivial algorithms and data structures, all the error handling, etc.

Templates don't "fix a problem with the language's type system", they simply add a number of fundamental capabilities almost completely absent from C and/or C++ without templates. One of the original intents was to provide for type-safe containers, but in reality they go far beyond that -- essentially none of which C provides at all.

Automated tools are mostly a red herring as well -- while it's true that writing a C parser is less work than writing a C++ parser, the reality is that it makes virtually no difference in the end. Very few people are willing or able to write a usable parser for either one. As such, the reasonable starting point is Clang either way.

As it happens, C and C++ are fairly frequently used together on the same projects, maintained by the same people. This allows something that's otherwise quite rare: a study that directly, objectively compares the maintainability of code written in the two languages by people who are equally competent overall (i.e., the exact same people). At least in the linked study, one conclusion was clear and unambiguous: "We found that using C++ instead of C results in improved software quality and reduced maintenance effort..."

6
  • 12
    Tool support is not a red herring. Granted, nowadays we have clang. But tool support for C++ does lag behind oder languages considerably, even in the big-shot IDEs. Why is that? Simple, because until very recently there was no clang (and GCC was never an alternative). Until maybe half a year ago, if you needed an AST of C++ code, you were basically out of luck or out of thousands of dollars (if you bought the EDG frontend). Commented Oct 10, 2011 at 7:26
  • 5
    +1, and for the record, I regularly write C++ code for 8-bit processors with 4KiB ROMs.
    – avakar
    Commented Oct 10, 2011 at 12:20
  • 2
    +1 for an overall great answer. What I do not understand (I have no experience wrt. this) is why (I guess we're talking embedded?) a C compiler should produce smaller executable code than a C++ compiler given the same feature set used? Maybe you could provide some references?
    – Martin Ba
    Commented Oct 10, 2011 at 13:23
  • 2
    @Martin: the main thing is that C++ includes exception handling, which (at least usually) adds some minimum to the executable size. Most compilers will let you disable exception handling, but when you do the result isn't quite C++ anymore. I suspect there's also a bit from the simple fact that many C++ compiler vendors just don't work quite as hard at producing the smallest possible output code. Commented Oct 10, 2011 at 15:04
  • 3
    "We found that using C++ instead of C results in improved software quality and reduced maintenance effort..." that is the conclusion to remember. Commented Aug 14, 2012 at 19:25
24
votes

The differences between C and C++ have already been enumerated in detail here. While sometimes people may have legitimate reasons for choosing one or the other (C++ for OOP or C when they feel like C++'s extra features introduce undesirable overhead, for example), in my experience it usually just comes down to preference. What do the people working on this file know better and like better? I believe this is the reason most of the time, since it's true that these languages both tackle performance critical applications.

(Side-note: Check out Linus Torvads' rant on why he prefers C to C++. I don't necessarily agree with his points, but it gives you insight into why people might choose C over C++. Rather, people that agree with him might choose C for these reasons.)

16
  • 51
    -1 for Linus's rant. :-{
    – sbi
    Commented Oct 10, 2011 at 6:18
  • 12
    Don't minus one me for that! Haha. I don't agree with Linus, but it's a pretty good example of WHY people might choose C over C++ (if they believe what Linus believes). I'm not commenting on the legitimacy of those reasons. Commented Oct 10, 2011 at 7:49
  • 10
    @CaseyPatton: Basically, I downvote every answer that presents this rhetoric rant uncommented as if it were a real argument.
    – sbi
    Commented Oct 10, 2011 at 7:56
  • 11
    @Coder: You don't have to know the STL implementation at all. The very point of the STL is that you don't have to know the implementation, unless you're relying on behaviour not defined by the Standard- in which case, why bother using the Standard library? Moreover, it's more than a tad insane to not like a language because of how it's developers behave. C programmers behave like C is God's gift to Man and are too blind to see the obvious truth that C++ offers features which are fundamentally and intrinsically directly superior to C, like RAII.
    – DeadMG
    Commented Oct 12, 2011 at 13:51
  • 8
    @Coder: If you end up with so many shared_ptrs to a single object that you overflow the internal counter, you're doing it wrong. The Standard will specify a minimum size for the counter- probably 32bit- and it's pretty unrealistic to have to have more than 2 billion shared_ptrs to one single object. Even if the object itself had 0 size, and you had a zero-overhead memory allocator, then you're still consuming 16GB of memory, just on shared_ptrs.
    – DeadMG
    Commented Oct 13, 2011 at 9:44
13
votes

The main problem missing from the existing answers (as of the time of this posting) is the choice.

It's simple. If, for some utterly irrational reason, you feel that exceptions aren't worth the overhead, then you don't have to use them. You can still have templates, and RAII, and the Standard library, and never write a single "throw". The same goes for templates. If, for some reason, you feel they cause irrevocable (and actually important, which it is only on embedded) executable bloat, then surprise- you can use void* and sizeof(T) all day too. Nothing forces you to use any of the C++ features over C.

That's why C++ is an inherently superior language- you can cherry pick the features you want, and fall back to C-style programming when you dislike a given feature. Therefore, given that C++ is everything C is and more, it's an obvious fact that C++ is a superior language. Suggesting otherwise is like trying to suggest that 4 is greater than 5.

8
  • 1
    Following your reasoning there is no point at all in the original question and therefore it should be closed. I guess the question should be read something like: when should we restrict ourselves to the C subset of C++ (use plain C) and when does it make sense to use full C++.
    – Giorgio
    Commented Oct 10, 2011 at 19:18
  • This is true, but only for cases of one person working on their own little project. In real life almost everyone spends maybe half their time working on other people's code. Unfortunately most other people "think wrong" regarding those utterly irrational reasons.
    – DarenW
    Commented Oct 10, 2011 at 19:44
  • 1
    @DeadMG: How are allocators meant to report errors without throwing exceptions? Also, adding more features is not necessarily better when all that it does is add complexity or redundancy.
    – Mankarse
    Commented Dec 2, 2011 at 4:30
  • @Mankarse: If you compile with the options to disable exceptions, allocators either abort the program or merrily proceed to use a null pointer, depending on the library implementation.
    – Zan Lynx
    Commented Jan 25, 2012 at 20:56
  • 4
    @Mankarse: Since my experience in 2007 when I tried running a Linux system with 1 GB RAM and no swap, almost all desktop software fails in horrible awful ways when memory allocation fails anyway.
    – Zan Lynx
    Commented Jan 26, 2012 at 7:06
9
votes

Things about C++ that make C programmers nervous

There's a lot of magic happening under the hood; constructors, destructors, virtual methods, templates, etc., can make C++ code a lot easier and faster to write than the equivalent C code, but harder to understand and reason through (depending on how well you know C++ and its associated conventions). Something as simple as Foo newFoo; may invoke a lot of code, depending on how the constructor for class Foo (and any classes it depends on) has been defined. This is also why the convention is to write ++it instead of it++ when iterating through a container, since postfix ++ often involves an expensive copy operation.

Depending on what you're doing, there can be some non-trivial overhead, especially for simple tasks. Take the following two programs, the first in C, the second in C++:

/* C version */
#include <stdio.h>
int main(void)
{
  char greeting[] = "Hello, world";
  printf("%s\n", greeting);
  return 0;
}
/* end C version */

/* C++ version */
#include <iostream>
#include <string>
int main(void)
{
  std::string greeting("Hello, world");
  std::cout << greeting << std::endl;
  return 0;
}
/* end C++ version */

Identical behavior, not a whole lot of difference in terms of source, but on the SLES 10 box I work on with gcc 4.1.2, the former generates an executable of ~9kb in size, whereas the second takes over 12.5kb (no optimization), almost 28% larger. The C++ string type is a lot easier to work with IMO than the C string library, and C++ streams are a lot more flexible and customizable than C streams, but for really brain-dead code like this, they may not be worth the overhead.

C++ is a huge language compared to C, with some extremely complex semantics. It takes a lot longer to get proficient with C++ than C, meaning a lot of people who claim to know C++ don't know it as well as they think they do.

Things about C that make C++ programmers nervous

C is not a secure programming language by any stretch of the imagination; no bounds checking on arrays leads to lots of exploitable behavior (be it through the now-dead gets function, or through scanf with the %s and %[ conversion specifiers). C++ at least gives you containers that throw exceptions if you try to access outside their currently defined range; all C gives you is (if you're lucky) a segmentation violation.

Memory management in C is very labor-intensive and error prone, compared to the tools C++ provides you. If you're building your own container, you're responsible for matching up all the malloc and free calls, making sure allocations are successful, backing out any partial allocations in the event of an error, etc. In C++, you just add items to or remove items from the container. If there's a problem, an exception will be thrown.

Similarly, error handling in C is a pain in the ass compared to the tools C++ provides (namely, exceptions). What's really fun is when you've allocated a bunch of memory and then hit a wall in your processing; as you have to back out, you have to release that memory in the right order. With C++ and RAII principles, this is (relatively) easy to do.

So when do I use one over the other?

If what you're writing is a bog simple, read it / muck with it / get rid of it application, whose behavior can be described cleanly in terms of inputs and outputs, and performance matters, then prefer C over C++. Otherwise, prefer C++

1
  • 2
    Memory management is complex and error prone in some cases, but especially in the embedded world it's often practical to write C programs using entirely static memory allocation. If the program links, it can't run out of memory at runtime. Can such guarantees be easily achieved in C++?
    – supercat
    Commented Feb 20, 2014 at 5:12
9
votes

Bjarne Stroustrup maintains a list of applications and companies that use C++; you can argue about procedural vs OOP programming all you want, but you cannot argue with industry results over the last 20 years.

C++ is commonly used for large-scale, multi-man, complex projects where separate people need to work on modularised components. You can build and maintain modularised code in C, of course, but the inherent OOP nature of C++ leads to superior modularisation, testability, and code-reuse.

The C++ standard library (STL), in itself with just vectors and maps, is reason enough to use C++.

C is commonly used for embedded systems.

I would personally use C only if there is some library that has only a C API.

2
  • 19
    Your final sentence isn't a reason to use C. You can call C libraries from C++.
    – user207421
    Commented Oct 9, 2011 at 22:46
  • 2
    I used c++ for a DSP project - not c Commented Sep 7, 2013 at 22:40
9
votes

I would say that the main reason why I would choose C over C++, is only when I would have to resort to "It this HAS TO BE 1000% stable" NASA kind of stuff.

C++ is ~99% C when we look at the performance, and it's a lot more productive. So even while in C you can write code that will be faster than C++ (you can use a subset of C++ without exceptions, virtual, streaming, abstractions, etc. as well, but that's basically C), the time to optimize every damn thing while STL is tested and does that already, would cost you more than the tiny performance gain you might achieve, or sacrifice because STL algorithms have been written by groups of experts, and you're probably not an expert in everything.

On the other hand C++ has a ton of abstractions. When under circumstance they leak, this gets you into trouble. And there are few people who know 100% of C++ gotchas, while, I guess, there are more that know all C gotchas, so writing a solution where every step is fully understood by all members of a team is a lot easier in C.

Example: Do you know when shared_ptr<smthn> will overflow its reference count, will it throw an exception? Things like these are not cool when Shuttle has to reenter the atmosphere, at least I guess so.

Also, exception handling is very, very hard compared to error codes. It's hard to see if the class is 100% exception safe, and easy to get into leaks. A lot of high rep people have expressed this opinion.

19
  • 12
    And in which way exactly is manually managing memory "more stable" than C++' abstractions like std::string and the like? Have you ever tried to specify a platform where shared_ptr's counter would overflow? That would be one heck of a funny platform. And if you think exception handling is hard, you ought to have a look at a piece of C code that checks for every possible error on every function call. (Such code is hard to come by, I admit, but this is just an even more strong argument against your statement.) Sorry, but this is genuinely bovine excrements.
    – sbi
    Commented Oct 10, 2011 at 6:24
  • 12
    @Lundin: '"It has to be 1000% stable" implementations don't allow dynamic memory allocation in the first place'. And what keeps you from doing exactly that in C++?? (And making blanket statements about my knowledge and experience rather than providing any arguments is a rather cheap rhetoric trick.)
    – sbi
    Commented Oct 10, 2011 at 7:08
  • 10
    @Lundin: Good that you have started to provide arguments, rather than rhetorics. But they are weak. That you have "forgotten" one of the main features of C++ (templates), one that makes code safer (because it allows algorithms to be executed - and thus, fail - at compile-time, eliminating run-time errors), does not speak in favor of your knowledge of the language you are judging. Reduction of C++ to an OO language has been criticized before here, and for good reasons. (Besides, classes with deterministic destruction are a great tool and helpful for managing other resources than just memory.)
    – sbi
    Commented Oct 10, 2011 at 10:11
  • 9
    @Lundin Of course you wouldn't want to use std::string if you don't want dynamic allocation. You'd use std::basic_string<char, std::char_traits<char>, some_allocator_here>.
    – Luc Danton
    Commented Oct 10, 2011 at 12:29
  • 10
    @Coder: What do you think you prove with these? The first one is simply bad code (and would be just as bad reporting errors as return values), the second one makes a case for RAII over manual cleanup to which every half-decent C++ dev would cheer, and Joel, as much as I respect him, did say a few things I strongly disagree with. His plug for single-entry-single-exit reeks badly of an uninformed old fart who will never agree that what he learned 25 years ago is surpassed. (Mind you, I was programming 25 years ago, when SESE was the state of the art.)
    – sbi
    Commented Oct 10, 2011 at 12:35
6
votes

C is portable assembly with better syntax, yielding the programmer full control of everything.

C++ on the other hand, does a lot of funky magic (virtual functions, overloading, automatic conversion, etc etc) which may not be desirable when you want to make sure you:

  • don't use more memory than you want to
  • don't access memory pages willy nilly (the vtable can be anywhere)
  • don't invoke to much code accidentally

And want something really simple to work with, since you're focused on performance.

It just has no surprises, and that's very valuable.

If you want to (and I recommend it), read the JSF coding guidelines on what you need to think about when writing C++ for military avionics control. It's a lot of traps in there that you need to be aware of, and it may catch you out. Bjarne was part of that document, so he knows what it's about.

Also, C compiles like a scalded troll struck by lightning. C++, OTOH, was probably sponsored by the same people who invested in SSD companies . :)

(Personally, I'd prefer C++ though, but I don't like it...... either. ;-P)

2
  • 1
    There are a lot of things C doesn't offer control over. Try writing efficient portable code to multiply a uint32_t by a uint32_t to yield a uint32_t result (bottom 32 bits of product). If an int is 64 bits, one must cast at least one operand to uint64_t to prevent Undefined Behavior, but having to cast to 64 bits for the purpose of computing a 32-bit result is--to put it mildly--"surprising".
    – supercat
    Commented Feb 20, 2014 at 5:18
  • It's not. The compiler does things like register allocations for you. I cannot write maintainable code in assembly, in C I can.
    – Nils
    Commented Apr 24, 2014 at 15:00
2
votes

(given you have equal familiarity with both languages)

Go with C++ unless there is no C++ compiler for your platform. You can write C++ code without whatever portion of the language you don't like (no classes, exceptions, virtual inheritance, whatever personal restrictions you wish to apply), and then at some time in the future, if you decide you want some of those features after all, then you can easily use them. Nothing in C++ prevents you from writing C-style code.

(given equivalent toolsets and developer knowledge) There is no reason to choose C over C++ provided your platform has a C++ compiler. You can simply limit yourself to the subset of the language you wish to today, while leaving the door open for extension later.

1
vote

Both languages are excellent. I think a number of posters have detailed the strengths and the various uses for each. I will simply add this:

I see the C language perfect in 4 areas: 1) I think it's the best language to use when first learning any type of programming [combined with some Assembly and knowledge of machine code], 2) it's great for writing drivers, 3) embedded software, and 4) system software at the lowest level.

C++ is an object-oriented language, but it can also be procedural (very much in the way of C). If you're working on large-scale projects, GUI-based software, gaming software, and other types of graphically-intensive software, then I find C++, Java, or even Objective-C to be your best choice. However, there is plenty of command-line programs or system software where you might find C++ to be as good or better than C.

0
0
votes

In my opinion there is one point missing in this discussion: It is simpler in C to provide a stable binary interface from a library. Both for usage with other languages as well as C++.

In C++ different compilers use different name mangling so consumers of a library compiled with a different compiler from the library might have issues using it. With C the binary interface, usually, is standardized for the platform.

I know that compilers nowadays often have switches to produce gcc-compatible things, but that doesn't always help.

I observe this on Solaris relatively often. The distribution and different software vendors typically use Sun Studio as, especially on Sparc systems, it often provides better results. Man open source projects are written with gcc-specific code though. Can be quite some pain to get those working together.

0
votes

C is probably preferable to C++ when the C code is generated (e.g. in implementations of higher-level languages). For example, there are several Lisp-like compilers which emit C code (e.g. Chicken, Scheme48 ...), but I know none which emits genuine C++ code (my MELT tool emits C++ code, but I won't call that code genuine C++ code, it uses very few C++ features).

C code is also easier to prove semi-automatically. Static analyzers like Frama-C (where you annotate your C code with ACSL comments to help the prover reason about your code) are available for C, but not that much for full C++11.

Not the answer you're looking for? Browse other questions tagged or ask your own question.