views:

1813

answers:

16

Hi,

I'm having a debate with a friend and we're wondering why so many open source projects have decided to go with C instead of C++. Projects such as Apache, GTK, Gnome and more opted for C, but why not C++ since it's almost the same?

We're precisely looking for the reasons that would have led those projects (not only those I've listed but all C projects) to go with C instead of C++. Topics can be performance, ease of programming, debugging, testing, conception, etc.

+25  A: 

C is very portable, much more than C++ was 10 years ago.

Also, C is very entrenched in the Unix tradition. Read more in 'The Art of Unix Programming', about Unix and OO in general, and about specific languages on unix (including C and C++).

gnud
The links are a very nice read.
Paggas
+15  A: 

A lot of the projects started before C++ was standardized, so C was the obvious choice and a change later would be hard. C was standardized about a decade before C++, and has been more nearly portable for even longer. So, it was largely a pragmatic decision at the time, inspired in part by the Unix heritage of using C for most code.

Jonathan Leffler
+21  A: 

There are numerous counter examples: everything based on Qt for one.

Also, on my Debian testing system:

edd@ron:~$ apt-cache rdepends libstdc++6|wc -l
4101

So that's 4101 packages depending on the basic C++ library. For comparison, I get about 14,982 for libc6 or roughly 3.6 as many. But it is not if there aren't any C++ projects in Open Source land.

Edit: Thinko on my part: as the C++ packages also depend on libc6, the ratio really is

(14982 - 4101)/4101 = 2.65

so there are roughly 2 1/2 times as many packages implemented in C than there are in C++.

Dirk Eddelbuettel
Does the 4101 include all the KpacKages depending on Qt? :-)
ShreevatsaR
But of Kourse :)
Dirk Eddelbuettel
+1 - someone who actually measured :)
Johannes Schaub - litb
+20  A: 

Eric Raymond's wonderful book "The Art of Unix Programming" has some reflections on this issue (the whole book is well worth reading in either the paper or free online editions, I'm just pointing to the relevant section -- Eric was involved with the coining and introduction of the term "open source", and is always well worth reading;-0).

Summarizing that section, Raymond claims that "OO languages show some tendency to suck programmers into the trap of excessive layering" and Unix programmers (and by extension open-source programmers) resist that trap of "thick glue".

Later in the book, you find some considerations specifically about C++, such as "It may be that C++'s realization of OO is particularly problem-prone". Whether you agree or not, the whole text is well worth reading (I can hardly do it justice here!-), and rich with bibliography pointing you to many other relevant studies and publications.

Alex Martelli
I think it's a fair point on OO. Of course, today, C++ is much less about OO, and this objection pretty much falls away, but when most of these projects (and the Unix philosophy) were being founded, C++ was nonstandard, and it was all about OO.
jalf
I've seen excessive data hiding at times. A minor requirement change can result in serious refactoring, or else everything gets made public out of desperation. Also, I can't help noticing that a key OOP principle (often expressed as "you don't draw the shape, the shape draws itself") is violated even by GOF design patterns. That's why I'm not embarrassed to write "tool" classes that do what they do to some other object. IMO, it's just a matter of doing what works rather than building ivory towers - OOP should be treated as a toolkit, not a religion.
Steve314
@jalf: The unix philosophy was formed some years before Apache was started...
gnud
+9  A: 

I have worked on a few C++ projects in my time, all of which have ended in tears one way or the other. At the most fundamental level, the truth is that people can't be trusted. They can't be trusted to write good code, they can't be trusted to debug it, and they certainly can't be trusted to understand it when they have to come back and modify it again weeks/months later.

C code doesn't have a lot of the weird stuff in C++ that makes it hard to debug (constructors/destructors, anything that happens with static global objects during cpp_initialize() time, etc.). That just makes it easier to deal with when developing and maintaining a big project.

Maybe I'm a luddite, but every time someone says "C++" around me I get shivers.

Carl Norum
Crappy developers will write crappy code in every language, its hardly C++'s fault when they write crappy C++. I'll counter your experience by saying that every C++ project I've worked on has been successful, the current one about 750,000 lines of code.
Brian Ensink
@Brian: I agree with you, but on the other hand, I'd far rather work with a mediocre C programmer than a mediocre C++ programmer. A mediocre C programmer can write usable code. A mediocre C++ programmer will make your program explode. The steeper learning curve might be a valid reason for preferring C
jalf
I agree with @Brian in principle, but in practice I have just seen too many disasters. I shouldn't say that the projects I worked on weren't successful; one in particular is an enormous success. Unfortunately a HUGE number of bugs can be tracked down to plain old awful programming. The fact that said awful programming was done in C++ just made it harder to debug.
Carl Norum
My experience on very large C++ projects is that it works just fine, FWIW. I'd strongly recommend mandatory code reviews to catch the bad stuff early.
David Thornley
What happens if the huge project started off as a small project, and people wrote a bunch of crap that the rest of us are forced to live with for all eternity? Time for refactoring and existing-code improvements is the first thing to crushed out of the schedule when the deadline rears its ugly head.
Carl Norum
I should clear up the point I'm trying to make, I guess. If you can trust everybody, there's not going be a problem. Heck, write it in 68k assembly for all I care. But C is clearly easier to debug later when you have some weird concurrency/operating system interaction bug, or if you have some driver that's not working quite right, thanks to finicky hardware. The domain of your problem is arguably just as important; if you can't trust provably correct code to work (because your hardware can fail), be wary of writing code where you don't explicitly control every single operation.
Carl Norum
+4  A: 

One important aspect in addition to others that will doubtless be mentioned is that C is easier to interface with other languages, so in the case of a library intended to be widely useful, C may be chosen even nowadays for this purpose.

To take examples I am familiar with, the toolkit GTK+ (in C) has robust OCaml bindings, while Qt and Cocoa (respectively in C++ and Objective C) only have proof-of-concepts for such bindings. I believe that the difficulty to interface languages other than C with OCaml is part of the reason.

Pascal Cuoq
+13  A: 

Linus Torvalds has ranted several times on the topic of C++ -- he uses C for git, and of course the Linux kernel is mostly C:

You can easily find more of these, and while it's in his nature to get a bit flamey about these things, there are some valid points.

One of the more interesting (from where I'm sitting, anyway) is the observation that C++ compilers and libraries were (and to some degree are) a lot more buggy than the corresponding C compilers. This stands to reason given the relative complexities of the two languages.

It smells a little of "not invented here" (NIH) syndrome, but when you have the entire Linux kernel developer base, you can sometimes afford to reinvent things "The Right Way".

leander
+1, and also Minix is written in C. :-)
LB
I'd like to point out that there's vast differences between 1998 C++ and 2009 C++, in practice anyway. The standard is generally implemented well in modern compilers, aside from corner cases and mistakes like "export". We now understand exception safety. The Boost project filled in some major holes, and some libraries are going into C++0X (X being in hex, of course). The reasons to use C instead of C++ were far stronger back then.
David Thornley
If C++0X is really hex, it's still about 39 years away.
jbcreix
Since when is `X` used in hex? Except as a prefix to the real number?
gnud
It's an X as in replace it with the correct number. You'd prefer a "." or maybe a "?". Anyways, the closest 0X year in hex is 2048, however they could keep delaying it until 2063.
jbcreix
+10  A: 

C++ is a mess. It is overly complicated language, so complicated that only few people can say that they know all the bits. And fewer compilers which really complies to C++ standard.

So I think the reason is simplicity and portability.

If you want higher-level and object-oriented programming, then I think C++ is just competed with others like Python. (Note that I programmed in C++ few years, it's fast and has some features from higher-level languages that speeds up development, no offence.)

Viliam
+1 because, though this is edging towards flamebait, I agree. C++ tries to do everything well, and ends up doing nothing spectacularly. Thus, for any task, C++ may do a decent job, but some other language always does a better job.
Chris Lutz
"ends up doing nothing spectacularly" - although there are some things it does which no other (commonly used) language does at all. So whether it does them spectacularly well becomes a difficult argument to have, since there's nothing to compare with. And I'm pretty sure it's true of all languages that there are fewer compliant implementations than there are people who fully understand the language. For it to be otherwise, those who understand the language would have to write more than one implementation each ;-)
Steve Jessop
It is not necessary to know all the bits to program effectively in C++. It is perfectly possible to use the libraries without knowing much about templates. (It is necessary to understand exceptions, though.) Nor are C++ and Python particularly similar: Python is easier to write in, and C++ is much more efficient to run.
David Thornley
I wonder how many people know all the bits of C? Possibly not much either.
Johannes Schaub - litb
ShreevatsaR
@ShreevatsaR: Have you actually seen the C standard? I assure you it is not for faint-harted.
Nemanja Trifunovic
Steve Jessop
ShreevatsaR
@ShreevatsaR: You don't need to be familiar with all of either standard to use either language well. You do need to learn more to use C++ effectively, but it's also easier to write a lot of things in C++ than C. It's easier to learn C well enough to write a simple program, but if you're going to work on a few large systems the learning time simply isn't that important compared to development time.
David Thornley
Steve Jessop
@onebyone: Note that the C++ standard which has 782 pages is much dense (roughly 2x, smaller font) then C99. Just an observation.
Viliam
Heh, good point. I make it 30-something lines per page of n1124, and 40-something longer lines of the C++ standard. But I don't think this detracts from my point, that C is not simple. Sure, complain that C++ is over-complicated and messy, and few users properly understand it. But really you have to read the definition of `restrict` in the C99 standard before being allowed to say with a straight face that many of the same concerns don't apply to C.
Steve Jessop
+7  A: 

As someone who dislikes C++ and would pick C over it any day, I can at least give you my impressions on the topic. C++ has several attributes that make it unappealing:

  • Complicated objects. C++ has tons of ability to speed up OO, which makes the language very complex.
  • Nonstandard syntax. Even today most C++ compilers support quirks that make ensuring successful and correct compilation between compilers difficult.
  • Nonstandard libraries. Compared to C libraries, C++ libraries are not nearly as standardized across systems. Having had to deal with Make issues associated with this before I can tell you that going with C is a big time saver.

That said, C++ does have the benefits of supporting objects. But when it comes down to it, even for large projects, modularity can be accomplished without objects. When you add in the fact that essentially every programmer who might contribute code to any project can program C, it seems hard to make the choice to go with anything else if you need to write your code that close to the metal.

All that said, many projects jump over C++ and go to languages like Python, Java, or Ruby because they provide more abstraction and faster development. When you add in their ability to support compiling out to/loading in from C code for parts that need the performance kick, C++ loses what edge it could have had.

Gordon Worley
I don't understand your "complicated objects," "tons of ability to speed up OO" point. Like, not that I disagree — I just don't get what you're saying there.
Chuck
The last point on libraries was true, but if you look at the way things have been recently, you'll observe otherwise. There are compilers available for every imagineable platform that support the full range of ISO C++ libraries, like GCC on anything remotely Unix, and Visual Studio on Windows. It is effectively standardised as far as STL etc. goes.
blwy10
@Chuck - Take for instance the keyword "virtual" - this exists solely because making every function virtual would incur a noticeable performance cost. It is an optimisation to make OO fast.
Tom Leys
@Tom: it’s a perfectly fine language convention. C# does it as well, and Java supports the opposite. Notice that in *neither* case is it used (primarily) for performance gain, since the JIT doesn’t require this kind of information. It is there to inform the *user*.
Konrad Rudolph
In C++, the `virtual` keyword is there explicitly so that non-virtual functions don't incur the extra overhead (and complexity). The c++ "mantra" is "don't pay for what you don't use".It also forces you to be explicit. Which is probably the best thing to come from it.
gnud
+8  A: 

If you look at recent open source projects, you'll see many of them use C++. KDE, for instance, has all of its subprojects in C++. But for projects that started a decade ago, it was a risky decision. C was way more standardized at the time, both formally and in practice (compiler implementations). Also C++ depends on a bigger runtime and lacked good libraries at that time. You know that personal preference plays a big role in such decision, and at that time the C workforce in UNIX/Linux projects was far bigger than C++, so the probability that the initial developer(s) for a new project were more comfortable with C was greater. Also, any project that needs to expose an API would do that in C (to avoid ABI problems), so that would be another argument to favor C. And finally, before smart pointers became popular, it was much more dangerous to program in C++. You'd need more skilled programmers, and they would need to be overly cautions. Although C has the same problems, its simpler data structures are easier to debug using bounds checking tools/libraries.

Also consider that C++ is an option only for high-level code (desktop apps and the like). The kernel, drivers, etc. are not viable candidates for C++ development. C++ has too much "under the hood" behavior (constructor/destructor chains, virtual methods table, etc) and in such projects you need to be sure the resulting machine/assembly code won't have any surprises and doesn't depend on runtime library support to work.

Fabio Ceconello
"The kernel, drivers, etc. are not viable candidates for C++ development." Not strictly true. The BeOS operating system was written in C++, and has it's devotees, but it did die, and since it was closed source it stayed fairly dead. It's possible to write such low level tools in C++, but not common, because few C++ programmers understand what the code they write will mean in terms of performance (due to all the abstractions). So while it's possible to write C++ as efficiently as C, it's rare, which is why C is used for low-level development.
Chris Lutz
Speaking of BeOS, there's actually a BeOS clone these days called Haiku, also written in C++. So yes, it's possible.
Chuck
+1 for the standardized ABI in C
yves Baumes
From what I recall, parts of the BeOS kernel *were* written in C... Not sure about Haiku, though.
Benjamin Oakes
I agree, Chris, when I said "not viable" I didn't mean it's not possible, just that it probably wouldn't be the best choice. I think in such cases the C code would be simpler and cleaner than C++, I don't see the advantage for using object orientation in such situations like interface to hardware I/O ports and the like, at least not at that level.
Fabio Ceconello
+4  A: 

One reason might be that the GNU coding standards specifically ask you to use C. Another reason I can think of is that the free software tools work better with C than C++. For example, GNU indent doesn't do C++ as well as it does C, or etags doesn't parse C++ as well as it parses C.

Kinopiko
That advice flies totally in the face of everything that GNU, and free software, stands for. Namely, giving maximum control and freedom of choice to the user (in this case: the programmer).
Konrad Rudolph
They're talking about people contributing to GNU itself, though. Their project, their rules. For the same reason, there are open source projects using curly-brace-on-a-new-line, not because the authors think it's better or worse than curly-brace-at-end-of-line, but because GNU says so.
Steve Jessop
Another example: OpenOffice had dependencies on Java, which caused no end of complaining, so last I heard the project made the Java dependency optional. So if GNU says, "if you want your project to be useful to the greatest number of people, the only installed language you should depend on is C", then they probably mean it.
Steve Jessop
A: 

You can read Dov Bulka to find what not to do in cpp, you can read tesseract ocr at Google code, you can read lots of things - most of which depend on where you are to determine which code linguistic is superior. Where did you read that c has more source code up in open source than cpp? Well of course you read that in a c forum. That's where. Go to some other programming linguistic. Do the same search, you will find that that code has more open source.

Nicholas Jordan
According to one survey, C is the most popular: http://www.theregister.co.uk/2009/01/21/open_source_projects_08/
Kinopiko
This is why people want to close questions like this as "subjective and argumentative." This is vaguely coherent, and makes unsourced (and unverifiable) claims as facts. -1
Chris Lutz
@Chris, noted. It's just that I have to deal with this on massive projects where one's entire existence can be crushed by people with no mechanical skills for reasons any mechanic would abhor. I get cornered on it so many times that I go braveheart at the sight of it. What makes the register the ultimate do-all be-all end-all any more than say roseinda or something? My source is my own experience, my verifier is fifty thousand hours in brutal arena where there are no verifiers. No mercy from the cruel, no rest for the wicked, no room for cream.
Nicholas Jordan
@Kinopiko - given, theregister is at the front of may of these discussions, so also Dr. Dobb's and so on - as noted in my original post: Dov Bulka, wherein a canonical discussion of my basis is given. Ditto Jeff Duntemann's intro to assembler - both those works express my basis for going frontline with my experience.
Nicholas Jordan
Just a side note about Tesseract OCR. It started off as a proprietary product by Hewlett-Packard, was abandoned, and then released as open source.
Kinopiko
@Kinopiko: noted and correct - they also made / make great contributions to stl
Nicholas Jordan
A: 

I can list a couple more reasons

  1. C code produces more compact object code. Try to compile 'Hello World' as C and C++ program and compare the size of the executable. May not be too relevant today but definitely was a factor 10+ years ago
  2. It is much easier to use dynamic linking with C programs. Most of the C++ libraries still expose entry points through C interface. So instead of writing a bridge between C++ and C why not to program the whole thing in C?
Alexander Pogrebnyak
Re: #1: On my computer (MacBook Pro), `hello-c` is 12588 bytes (12.3 kB), and `hello-cpp` is 13068 bytes (12.7 kB). Not significant, but that's probably because OS X uses the bloated Mach-O format for binaries.
Chris Lutz
+8  A: 

Some people have mentioned portability, but in this day, the portability of C++ isn't much of an issue (it runs on anything GCC runs on, which is essentially anything). However, portability is more than just architecture-to-architecture or OS-to-OS. In the case of C++, it includes compiler-to-compiler.

Let's discuss ABI, or Application Binary Interface. This basically means "how your code translates into assembly." In C, when you write:

int dostuff(const char *src, char *dest);

You know that you're making a symbol in your object file called _dostuff (C global names are all prefixed by an underscore in the resultant assembly). But in C++, when you write this:

int dostuff(const char *src, char *dest);
int dostuff(const char *src, char *dest, size_t len);

Or even:

int dostuff(std::string src, std::string dest);

All bets are instantly off. You now have two distinct functions, and the compiler has to make each, and has to give each a unique name. So C++ allows (where I believe C doesn't) name mangling, which means those two functions might get translated to _dostuff_cp_cp and _dostuff_cp_cp_s (so that each version of the function that takes a different number of arguments has a different name).

The problem with this is (and I consider this a huge mistake, even though it's not the only problem with cross-compiler portability in C++) that the C++ standard left the details of how to mangle these names up to the compiler. So while one C++ compiler may do that, another may do _cp_cp_s_dostuff, and yet another may do _dostuff_my_compiler_is_teh_coolest_char_ptr_char_ptr_size_t. The problem is exacerbated (always find a way to sneak this word into anything you say or write) by the fact that you have to mangle names for more than just overloaded functions - what about methods and namespaces and method overloading and operator overloading and... (the list goes on). There is only one standard way to ensure that your function's name is actually what you expect it to be in C++:

extern "C" int dostuff(const char *src, char *dest);

Many applications need to have (or at least find it very useful to have) a standard ABI provided by C. Apache, for example, couldn't be nearly as cross-platform and easily extensible if it was in C++ - you'd have to account for the name mangling of a particular compiler (and a particular compiler version - GCC has changed a few times in its history) or require that everyone use the same compiler universally - which means that, every time you upgrade your C++ compiler with a backwards incompatible name-mangling scheme, you have to recompile all your C++ programs.

This post turned into something of a monster, but I think it illustrates a good point, and I'm too tired to try to trim it down.

Chris Lutz
It's not a good point: see http://www.parashift.com/c++-faq-lite/compiler-dependencies.html#faq-38.9
Kinopiko
I don't see anything there that _doesn't_ back up my core argument that C++ isn't binary compatible from compiler to compiler.
Chris Lutz
"The problem is (and I consider this a huge mistake, though I'm not versed in the potential reasons for this decision) that the C++ standard left the details of how to mangle these names up to the compiler. " - this part is wrong, and it's perpetuating a myth. Somewhere there is an interview with Bjarne Stroustrup where he demolishes this criticism but I couldn't find it on the web so I posted the FAQ link. Name mangling is not the problem.
Kinopiko
I still think that a standardized name mangling scheme, while not the only problem to be solved, would at least be a decent push towards cross-compiler compatibility, and minimize the damage (even if it can't be completely accounted for due to vtables). But I will take out the offending line.
Chris Lutz
@Kinopiko: Your link actually agrees with Chris, but goes on to say that the problem he's describing is just the tip of the iceberg when it comes to C++'s portability problems.
Chuck
Lol for "_dostuff_my_compiler_is_teh_coolest_char_ptr_char_ptr_size_t" :D
yves Baumes
Just for the sake of completeness, the underscore name-mangling of C symbols is a windows trait. I'm not aware that other OS ABIs follows such a convention :-)
Mads Elvheim
@Mads - It's pretty standard. Compiling `int dostuff(void); int main(void) { dostuff(); return 0; }` (i.e. not defining a `dostuff()` function anywhere) gives me a linker error saying `"no symbol _dostuff"` here on OS X. The underscore prefix is a de-facto standard.
Chris Lutz
@Mads: I've seen name mangling done in gcc on Fedora, so it's not just Windows. The issue is really that C++ has a much more complicated ABI, and it really wasn't the sort of thing that could be standardized by committee, and no de facto standard developed (as it did in C).
David Thornley
It should be pointed out that there is no "standardized C ABI" either. You won't be able to link GCC and MSVC code together based on "Standard ABI" meanings. Everything is platform dependent.
Johannes Schaub - litb
@litb - It's not a part of a formal standard, but there is a de-facto standard ABI for C because there really isn't anything in the language that requires extensive mangling to translate to machine language.
Chris Lutz
No, there's a de-facto standard ABI (on a given platform) for C because usually the people who design the chip provide one, whereas they rarely provide one for C++. In fact, there are at least *three* de-facto standard C ABI's to choose from on ARM ;-). An ABI requires far more than just a name-mangling scheme, it also requires a parameter-passing convention, register save rules, struct layout rules, possibly a stack layout, the list goes on. For C++ it needs a bunch of other stuff too: virtual call system, pointers-to-members, RTTI, exceptions...
Steve Jessop
"they rarely provide one for C++" - and, I should add, even if they did provide one it would most likely still be effectively impossible to write a back-end for Your Favourite Compiler which output code using that ABI, and so it would fail to become a de facto standard.
Steve Jessop
If one of the things we are talking about is that all those cool interpreters (perl, python, ruby, and ok, Java) need to do native language interfaces, then I have to say that Chris is 100% right.
DigitalRoss
A: 

First of all, some of the biggest open source projects are written in C++: Open Office, Firefox, Chrome, MySQL,...

Having said that, there are also many big projects written in C. Reasons vary: they may have been started when C++ was not standardized yet, or the authors are/were more comfortable with C, or they hoped that the easier learning curve for C would attract more contributors.

Nemanja Trifunovic
I thought, that OO is using Java
Juraj Blahunka
A: 

If correctly implemented C is very fast and very portable and the compilers are there

C++ is different for each compiler available, the libraries dont agree, the standards don´t match

This is my answer maybe other developers will not agree to it, sorry

Arabcoder