163

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

Anonymous
  • 3,546
  • 2
  • 25
  • 26
Dark Templar
  • 6,223
  • 16
  • 46
  • 46
  • 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 Oct 09 '11 at 18:49
  • 1
    If you do use C, try to keep your code also valid as C++. – Pubby Oct 09 '11 at 20:25
  • 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, `const`ness, `private`, RAII to make resource management manageable, etc.) over C. Or for that matter, use Ada or something in the first place. –  Oct 09 '11 at 20:33
  • delnan, I didn't say they drop to C because C has inherently better performance, but so they can optimize it. A programmer very familiar with how the compiler turns C into asm can write C code that is optimized better than what the compiler can do, without having to write raw assembly. – kylben Oct 09 '11 at 21:00
  • As to C++ producing more optimal code, that may be true for naive code written on design and maintainability criteria, but there is nothing in C++ that can't be done in C with enough extra code (aside from access limitations, which can be gotten around in C++ anyway), and a really good C programmer can write anything C++ can do better than C++ can do it, if its worth the extra effort. – kylben Oct 09 '11 at 21:06
  • 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 Oct 10 '11 at 01: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 Oct 10 '11 at 06:36
  • 4
    And if you believe C++ code needs to be naive in order to outperform C, then you might want to have an actual look at the STL. (Hold on to your hat, though, because if anything is naive here, it's your uninformed prejudices.) Also: For five decades none of the many "really good C programmers" have come up with a way to write an efficient generic sort algorithm. Of course, that shouldn't hinder you from expecting it to happen anytime soon, but the rest of us will, meanwhile, resort to the STL for combined speed and expressiveness. – sbi Oct 10 '11 at 06:37
  • @Dark Templar You can probably get 1000+ threads, essays and papers regarding this very topic if you Google. Likely on this site as well. –  Oct 10 '11 at 08:24
  • 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. – dsocolobsky Jun 21 '12 at 21:02
  • 2
    Just use C/C++. – Joachim Sauer Apr 08 '13 at 12:44
  • duplicate of: [When is C a better choice than C++?](http://programmers.stackexchange.com/q/39225/31260) – gnat Apr 13 '13 at 20:20
  • @dysoco Since when does C++ have virtual constructors? – fredoverflow Sep 06 '14 at 14:24
  • @dysoco: Since when did C++ look like a "C with classes"? – Lightness Races in Orbit Sep 06 '14 at 14:32

12 Answers12

185

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++.

sbi
  • 9,992
  • 6
  • 37
  • 56
  • 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 Oct 10 '11 at 00:26
  • 7
    @Coder: I suppose that, in an OS kernel, you simply must not call any functions that might raise exceptions. Since there is very few stuff in the language/std lib that throws exceptions, and since most of it (like `new`) is ruled out in an OS kernel anyway, I do not see how this applies. – sbi Oct 10 '11 at 06:28
  • 4
    Note, however, that Comeau C++ produces C as output, and they provide porting to almost any C compiler, so essentially anything that supports C can also support C++, though it might require enough more resources, that on a small system it would have to be run as a cross-compiler (even though the C compiler ran natively). – Jerry Coffin Oct 10 '11 at 06:29
  • @Jerry: That is true. However. Comeau has to be ported to targeting a specific C compiler. Unless you are targeting GCC, in which case you already have a reasonable C++ compiler, you need to plan that cost. Porting is offered by Comeau comparatively cheap, but not for free. – sbi Oct 10 '11 at 06:45
  • I don’t agree with point 3 – why can’t you use C++ here? You also didn’t say *why* you’d pick C++. An executive summary would be nice, especially since all other answers got this so phenomenally wrong. Since there are already good answers on other questions – [*cough*](http://programmers.stackexchange.com/questions/29109/is-there-any-reason-to-use-c-instead-of-c-perl-python-etc/29136#29136) – link to one if you’re lazy. ;-) – Konrad Rudolph Oct 10 '11 at 07:18
  • @sbi Sorry, I had skipped that part of the sentence somehow. – Konrad Rudolph Oct 10 '11 at 11:20
  • 7
    I'd add one more important reason, why Linux Kernel is in C. C is lingua franca of the programming world, allowing everyone with moderate skill to start coding right away. C++ after first hundred lines of code starts getting "flavors" and 10,000 lines into the project you don't code in C++ any more, just some specific meta-language you have built using C++ templates, class structure and design patterns. And anyone joining the project needs to learn that meta-language from scratch, taking a good month to catch up. – SF. Oct 10 '11 at 12:39
  • 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 Oct 10 '11 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 Oct 10 '11 at 12:45
  • 7
    @SF Take this with a grain of salt, but C is to programming what Latin is to the scientific community... When it comes to being "lingua franca" that is. It's still a useful language. – Max Oct 11 '11 at 01:23
  • 18
    @Max: I completely disagree. C is a useless language, unless some insurmountable practical barrier prevents the use of C++. – DeadMG Oct 12 '11 at 15:45
  • 7
    @DeadMG, I completely agree with you :). I HATE C. I love C++. – Stephane Rolland Aug 14 '12 at 19:22
  • 1
    The only thing I would add to this is that C can be the only option when you are faced with draconian memory limitations. – Lucina Sep 27 '12 at 07:40
  • @Buttons: Why would that be a reason to pick C over C++? – sbi Sep 27 '12 at 08:17
  • @sbi Because C++ programs tend to use more memory than C counterparts. – Lucina Sep 27 '12 at 08:42
  • 3
    @Buttons: No, usually they don't. They do automate some tedious tasks, though, like resource cleanup, or dynamic dispatch. If you are short of resources, why would you dismiss this advantage? I agree, though, that it is helpful to know the general "resource costs" associated with certain C++ features (for example, virtual functions) and make your decisions about which ones to employ when and where based on that knowledge. – sbi Sep 27 '12 at 08:45
  • 1
    @sbi Do you have a citation? Are you saying that C++ programs usually use _less_ memory than C? Of cource C++ programs _can_ use less memory, but that's why I said usually. – Lucina Sep 27 '12 at 08:49
  • 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 Sep 27 '12 at 09:41
  • 1
    +1 for if u don't know c++... – A.s. Bhullar Apr 21 '14 at 09:08
  • One thing no one mentioned is that C has a simple and well-defined ABI, which is what makes it easy to interface to other languages with just a few assembly instructions. That is (IMO) the most convincing reason to use C, in a compatibility layer for example. – Dan May 07 '14 at 16:48
  • @Dan: What's the difference to my third bullet? – sbi May 07 '14 at 16:54
  • @sbi I'm expanding on it. – Dan May 07 '14 at 17:39
88

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..."

Jerry Coffin
  • 44,385
  • 5
  • 89
  • 162
  • 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). – Konrad Rudolph Oct 10 '11 at 07:26
  • 5
    +1, and for the record, I regularly write C++ code for 8-bit processors with 4KiB ROMs. – avakar Oct 10 '11 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 Oct 10 '11 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. – Jerry Coffin Oct 10 '11 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. – Stephane Rolland Aug 14 '12 at 19:25
  • c++ code size and exceptions: earlier variants of exception handling were smaller. along the way, many went to use zero cost exceptions. in many regards, ZCEs are better -- binary size is the big penalty. some memory constrained systems do not use ZCEs in order to reduce the binary sizes (they use `*jmp`s for exceptions). – justin Aug 15 '12 at 00:57
24

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.)

Casey Patton
  • 5,211
  • 7
  • 33
  • 41
  • 2
    Someone should give Torvalds a "*Get well soon! Love, Java Programmer*" card. :) – Mateen Ulhaq Oct 10 '11 at 06:09
  • 51
    `-1` for Linus's rant. :-{ – sbi Oct 10 '11 at 06: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. – Casey Patton Oct 10 '11 at 07:49
  • 10
    @CaseyPatton: Basically, I downvote every answer that presents this rhetoric rant uncommented as if it were a real argument. – sbi Oct 10 '11 at 07:56
  • 7
    Definitely -1 for the Linus rant. He's uninformed and doesn't have a clue. If you don't want to agree with his points, don't post the link. – DeadMG Oct 10 '11 at 09:20
  • 1
    @CaseyPatton -- perhaps Linus overstates the problem, but, the tendency of some C++ programmers to over complicate in the name of abstraction is very real. – James Anderson Oct 10 '11 at 10:22
  • 4
    Linus has a point, somehow C++ developers behave like they know it all, while most don't have a clue, and even experienced ones rarely know 100% of the dark corners. I'm C++ developer myself, and I still occasionally run into some language issues. I wouldn't want to write OS kernel in C++, too easy to trip on a landmine. I love C++, but it's overly complex for systems that have to be 100% correct. Especially if the code has to cross compile on multiple platforms/compilers. Basically you have to know internal implementation of STL on each of them to be sure your code is right. – Coder Oct 10 '11 at 15:34
  • 6
    @Coder: I agree with you. I have been coding in C++ for over 15 years now and I keep coming across features I did not know of (and the language keeps growing :-) ). This is especially annoying when working in a larger team where each programmer uses their own dialect of the language: it makes reviewing and debugging code more time-consuming and error prone. In this respect I find C code much easier to read. But, yes, I miss containers and OOP when programming in C. So I guess you have to choose according to the kind of project you are working in. – Giorgio Oct 10 '11 at 17:00
  • 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 Oct 12 '11 at 13:51
  • 2
    @DeadMG: If I'm not mistaken, list of exceptions `std::something` can throw is not specified. For example `shared_ptr` overflow will depend on internal counter variable type. Is it size_t, linked list, will it throw? Looking at the current implementation I'm using, it's long, which is signed, so != size_t. And here lies the problem, if you don't know what to catch, you either `catch(...)`, in which case you don't know what to do, and might keep running on corrupt data, or you don't catch, and let the app crash. In 99.999% stable apps you can't allow that. – Coder Oct 12 '11 at 14:16
  • 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 Oct 13 '11 at 09:44
  • 1
    @DeadMG: You do have to know STL (rather, C++ Standard) implementation in some cases. Such as when debugging a multithreaded crash caused by std::string reference counting in earlier versions of GCC. These kinds of things would be very important in an OS kernel. – Zan Lynx Jan 25 '12 at 20:59
  • 2
    @ZanLynx: Did you really argue that one has to know the internals of some library in order to find bugs in its implementation? And was that really meant to support the argument that you cannot use the STL without knowing its internals? (That's certainly nonsense.) – sbi May 02 '12 at 07:34
  • 3
    @sbi: I argued that in some cases you have to know the internals. What, are you just going to wait around sitting on your hands when your program has a serious bug, waiting for the library implementers to get around to your bug report in five or six weeks? Good luck with that. – Zan Lynx May 02 '12 at 08:46
  • 6
    @ZanLynx: Of course you got to understand the internals of some lib if you want to debug into a broken implementation of it. But this is true for _any_ lib, including C ones, so to post it as an argument here is genuine bovine excrements. – sbi May 02 '12 at 09:32
  • 4
    @sbi: Do programmers use threads? Yes. Do some versions of the libstdc++ implementation contain std::string reference counting bugs? Yes. Does std::auto_ptr call destructors of forward declared classes properly? It depends on the implementation. Do some programmers need to support C++ applications running on those platforms? Yes. Therefore, DeadMG's claim that a programmer does not need to know anything about the implementation is false, because no such thing as a perfect C++ library exists. Is the knowledge needed to find bugs in the implementation? No, it is needed to work around the bugs. – Zan Lynx May 02 '12 at 23:14
13

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.

DeadMG
  • 36,794
  • 8
  • 70
  • 139
  • 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 Oct 10 '11 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 Oct 10 '11 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 Dec 02 '11 at 04: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 Jan 25 '12 at 20:56
  • @ZanLynx: So basically what you are saying is - "you can disable exceptions and still use the standard library, but only if you want to write incorrect programs". – Mankarse Jan 26 '12 at 03:01
  • 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 Jan 26 '12 at 07:06
  • @ZanLynx: That is because a lot of desktop software on Linux is based on QT, which is [horribly filled with bugs](http://doc.qt.nokia.com/4.8-snapshot/exceptionsafety.html). – Mankarse Jan 26 '12 at 08:01
  • I quite disagree on this answer, simple things can be superior to powerful but complex ones. and C++ is quite complex – Xavier Combelle Jul 24 '14 at 16:19
9

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.

tofi9
  • 211
  • 2
  • 7
stackoverflowuser2010
  • 2,736
  • 2
  • 18
  • 14
9

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.

Allen
  • 101
  • 4
Coder
  • 6,958
  • 5
  • 37
  • 49
  • 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 Oct 10 '11 at 06:24
  • 4
    @sbi "It has to be 1000% stable" implementations don't allow dynamic memory allocation in the first place. C has a popular, well-tried subset for safety-critical applications called MISRA-C. C++ has a similar one, but it is still new and as far as I know far less successful. Most safety-critical applications are written in either C or Ada. Also, if you have no experience or knowledge about such applications you probably shouldn't go around making statements about them. –  Oct 10 '11 at 06:57
  • 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 Oct 10 '11 at 07:08
  • 3
    @sbi C++ sort of implicitly assumes that you have a heap. If you use C++ without STL templates and things like std::string etc, there isn't much of a point in using C++, is there? What's left if you remove that, are the classes, somewhat stronger typing. (Various fluff like exception handling, function overloading etc can't be used in safety-critcal applications, so we can disregard those.) The C++ classes by themselves aren't that fantastic, they merely allows slightly more elegant OO programming than C does. Private encapsulation and heritage can be done in C, though in more crude ways. –  Oct 10 '11 at 08:18
  • @sbi Regarding your experience, there are no secret tricks. I can tell by your answer to the original question that you aren't working with safety-critical applications. –  Oct 10 '11 at 08:22
  • 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 Oct 10 '11 at 10:11
  • 2
    @sbi Umm no I haven't, I mentioned it in my post (maybe add a comma between STL and templates). Whether templates lead to safer code because of stronger typing, or unsafer code because of the additional complexity can be debated. Generally, you avoid templates in any embedded system just because they can lead to increased program size. Yes, you can avoid that if you are careful, but the same can be said about dynamic memory allocation. Here's a link to the rationale from the Embedded C++ committee http://www.caravan.net/ec2plus/rationale.html, listing C++ features you better avoid in embedded. –  Oct 10 '11 at 10:57
  • 1
    @sbi: "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. ", but at least it's easy verifiable. See: http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx, http://blogs.msdn.com/b/mgrier/archive/2004/02/18/75324.aspx, http://www.joelonsoftware.com/items/2003/10/13.html, http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx – Coder Oct 10 '11 at 11:30
  • 4
    @Lundin: That code bloat argument is 15 years old and had merits _back then_, but is pure FUD today. All the C++ gurus who have even commented on EC++ have basically laughed about it. I have done template meta-stuff, and the major reason I started to fiddle with it was that it can help to catch errors at compile-time. (With a multi-MLoC codebase, several million desktop installations, some critical servers, a few major players in the software industry as OEM partners, but not even a dozen devs and no support department, we might not have met NASA standards, but we had toi be quite good, too.) – sbi Oct 10 '11 at 12:21
  • 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, some_allocator_here>`. – Luc Danton Oct 10 '11 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](http://stackoverflow.com/q/76796/#77893) 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 Oct 10 '11 at 12:35
  • 2
    @sbi: That exceptions are too difficult for most people, myself including. If I need stability and reliability, I can't rely on them. Because then I have to know all the exception hierarchy which is not even my code in most cases, and, almost always, very badly documented. Exceptions are only good for one thing, if you don't catch them, then, the app fails-fast, which is a good thing for most commercial apps. – Coder Oct 10 '11 at 12:52
  • 4
    @Coder: As I said, the first example isn't even about exceptions vs. return codes, so it doesn't prove anything at all. Well, except that _error handling_ is hard, maybe. And I have never known the full exception hierarchy of any 3rd-party code I ever used, because exceptions are for, um, _exceptional_ circumstances, and not for common result reporting. If a lib throws an exception then I expect that something nasty happens, and I am content with catching it by `const base&` and logging its dynamic type and message. No need to catch objects of any derived classes. – sbi Oct 10 '11 at 13:31
  • @sbi: That's why, IMHO, C++ is a shitty tool for security oriented, high reliability systems. Because in those, you have to KNOW and handle everything, or nop slide to a safe state if you can't. – Coder Oct 10 '11 at 14:02
  • @Coder: _Sigh._ This is tiring. You do handle everything the way I proposed. Please read up on the subject. You seem to know too little to discuss this. – sbi Oct 10 '11 at 14:18
  • 1
    @sbi: HOW?! You say you handle? Well std::string can throw an exception (unknown/implementation specific) in a middle of data structure update routine. HOW WILL YOU HANDLE IT?! Shuttle is entering the atmosphere and it needs navigation data, HOW YOUR CODE WILL HANDLE THAT? You catch and log it in a global handler? Nice try... – Coder Oct 10 '11 at 14:38
  • 4
    @Coder: Did I mention you need to read up on the subject? – sbi Oct 10 '11 at 14:46
  • 2
    I would like to add that there is one better alternative to both error codes and exceptions: knowing your damn preconditions! – isekaijin Jul 31 '13 at 03:13
  • Not sure how much truth there is to this, but I imagine a vendor's C compiler is less buggy than its C++ compiler (assuming said vendor has both). This may be a legitimate reason to choose C over C++. And this is what I thought your post was going to be about when I read the first paragraph, but alas, it was not. – Thomas Eding Apr 14 '14 at 23:13
9

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++

John Bode
  • 10,826
  • 1
  • 31
  • 43
  • 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 Feb 20 '14 at 05:12
6

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)

nairware
  • 179
  • 6
Macke
  • 2,576
  • 16
  • 16
  • 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 Feb 20 '14 at 05: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 Apr 24 '14 at 15:00
2

(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.

anon
  • 1,474
  • 8
  • 8
1

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.

Jonathan
  • 1
  • 1
0

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.

johannes
  • 3,601
  • 2
  • 26
  • 32
0

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.

Basile Starynkevitch
  • 32,434
  • 6
  • 84
  • 125