One day I decided to start writing a video game in plain old C.
It was a lot of fun, and three months later (I sometimes have little time away from the job) I found myself in the need of some physics engine.
I decided to use Bullet physics engine, because it seems like one of the better ones out there for what I need.
Then, I found out Bullet doesn't really have a C API but only a full C++ API. Its C API is not maintained.
After a day of cursing, I 'converted' my project into C++, which is a bold statement for saying I typecasted all heap allocation and I use new and delete instead of malloc and free, and wrapped up some definitions in 'extern "C" { ... }'.
Some people would probably shoot me for doing that, but I saw no other option to using a performance-tasking thing such as this physics engine, which only has a C++ API, in C.
So now, I'm compiling with g++, while still writing mostly "C" code.
I find myself a little less happy, because the code no longer feels as pure.
C++ gives me some strange error messages, while I have nothing against the language I often do not like the g++ parser.
Aside from the fact that I can now happily bounce objects into each other, some of the smallness and purity of my pet project has been deserted now.
I'm wondering if I did the right thing. Can I ask for some advice, should I just carry on and not worry about using a C++ compiler for my 'mostly' C code? Are there other ways to use this API in C without any performance hits or overdone maintenance work?
I'm wondering if I did the right
thing.
Well, you needed a component for your project, and instead of inventing it again from scratch, you reused an existing piece of software. It actually sounds right to me.
Can I ask for some advice, should I
just carry on and not worry about
using a C++ compiler for my 'mostly' C
code?
You don't need to worry at all. C++ is almost 100% C compatible. There are no penalties on doing that. You have actually earned better compile-time checkings due to a much stricter type system.
Are there other ways to use this API
in C without any performance hits or
overdone maintenance work?
No, you can't use the API in C without converting your code to C++. C++ identifiers are mangled: this means that, even if you were ready to use the C++ API from plain C, you wouldn't know how to refer to them. Theoretically this is possible, in practice it isn't.
Your way is the correct one.
Good luck with that game!
I think you're overly concerning yourself with things that aren't really problems. You say that some of the purity has gone. Well, I can understand this. You wrote it in C and then, realizing you had to use C++ to use an API of choice, shoehorned it in. Now it doesn't feel like your pet baby anymore. This is a subconscious issue, not a programming one.
I suggest you bite the bullet (haha), and rewrite your project in C++. Then it will be pure again, you'll learn a lot on the way, and won't feel like your C-child is being sodomized.
Depending on how tightly coupled the different subsystems of your engine are, it might be feasible to write different parts of the engine in different languages.
For example, you could factor out the physics part into a C++ module which exports a C API and let the rest of your application stay in C. However, it might make more sense to write the central part of the system in C++ and refactor your existing C code into seperate modules.
If you want to write your project in C, write it in C and make a C wrapper for the library; have a look at this question for some advice about it.
Otherwise, rewrite your project in C++; but please, don't write yet another C project with some C++ here and there, in my experience these projects can quickly become a mess (and if you write code with a C mindset but calling C++ code weird things start to happen when exceptions are added to the mix).
Don't worry about writing mostly C code and compiling it with C++. Just adopt using new/delete instead of malloc/free and you'll be fine. The advantage of using new is that you don't have to cast the result to the proper pointer type (implicit casts from void* to other pointers are disallowed in C++) and that new will never return an invalid pointer. You loose realloc() though. (And no, don't even think of mixing new/delete with realloc :))
The only reasons you would keep a project as "pure C" are either because of source code compatibility, tool support, or because of language standards (MISRA-C etc). "I want it to feel pure" is probably not a very rational argument.
If keeping the code as pure C for such reasons is important, your could have written a "wrapper" DLL (assuming Windows) in C++, which does all the communication with your 3rd party API. You'd get a fair bit of overhead of course.
The strange error messages are no doubt caused by the stricter typing in C++, which can be a bless or a curse depending on the situation. A C++ compiler will be more likely to slap your fingers when encountering dangerous implicit typecasts (integer promotions etc) and it will likely enforce stricter "const correctness". But at the same time, it will moan about void pointers, which are considered good generic programming in C, but dangerous, sloppy and possibly redundant in C++.
One option is to convert the C++ code to C using LLVM. See this FAQ from the project's website: Can I convert C++ code to C code?
Related
I've been writing a number of network daemons in different languages over the past years, and now I'm about to start a new project which requires a new custom implementation of a properitary network protocol.
The said protocol is pretty simple - some basic JSON formatted messages which are transmitted in some basic frame wrapping to have clients know that a message arrived completely and is ready to be parsed.
The daemon will need to handle a number of connections (about 200 at the same time) and do some management of them and pass messages along, like in a chat room.
In the past I've been using mostly C++ to write my daemons. Often with the Qt4 framework (the network parts, not the GUI parts!), because that's what I also used for the rest of the projects and it was simple to do and very portable. This usually worked just fine, and I didn't have much trouble.
Being a Linux administrator for a good while now, I noticed that most of the network daemons in the wild are written in plain C (of course some are written in other languages, too, but I get the feeling that > 80% of the daemons are written in plain C).
Now I wonder why that is.
Is this due to a pure historic UNIX background (like KISS) or for plain portability or reduction of bloat? What are the reasons to not use C++ or any "higher level" languages for things like daemons?
Thanks in advance!
Update 1:
For me using C++ usually is more convenient because of the fact that I have objects which have getter and setter methods and such. Plain C's "context" objects can be a real pain at some point - especially when you are used to object oriented programming.
Yes, I'm aware that C++ is a superset of C, and that C code is basically C++ you can compile any C code with a C++ compiler. But that's not the point. ;)
Update 2:
I'm aware that nowadays it might make more sense to use a high level (scripting) language like Python, node.js or similar. I did that in the past, and I know of the benefits of doing that (at least I hope I do ;) - but this question is just about C and C++.
I for one can't think of any technical reason to chose C over C++. Not one that I can't instantly think of a counterpoint for anyway.
Edit in reply to edit: I would seriously discourage you from considering, "...C code is basically C++." Although you can technically compile any C program with a C++ compiler (in as far as you don't use any feature in C that's newer than what C++ has adopted) I really try to discourage anyone from writing C like code in C++ or considering C++ as "C with objects."
In response to C being standard in Linux, only in as far as C developers keep saying it :p C++ is as much part of any standard in Linux as C is and there's a huge variety of C++ programs made on Linux. If you're writing a Linux driver, you need to be doing it in C. Beyond that...I know RMS likes to say you're more likely to find a C compiler than a C++ one but that hasn't actually been true for quite a long time now. You'll find both or neither on almost all installations.
In response to maintainability - I of course disagree.
Like I said, I can't think of one that can't instantly be refuted. Visa-versa too really.
The resistance to C++ for the development for daemon code stem from a few sources:
C++ has a reputation for being hard to avoid memory leaks. And memory leaks are a no no in any long running software. This is to a degree untrue - the problem is developers with a C background tend to use C idioms in C++, and that is very leaky. Using the available C++ features like vectors and smart pointers can produce leak free code.
As a converse, the smart pointer template classes, while they hide resource allocation and deallocation from the programmer, do a lot of it under the covers. In fact C++ generally has a lot of implicit allocation as a result of copy constructors and so on. As a result the C++ heap can become fragmented over time and daemon processes will eventually fail with an out of memory error even though there is sufficient RAM. This can be ameliorated by the use of modern heap managers that are more fragmenttation resistant, but they do this by consuming more resource up front.
while this doesn't apply to usermode daemon code, kernel mode developers avoid C++, again because of the implicit code C++ generates, and the exceptions C++ libraries use to handle errors. Most c++ compilers implement c++ exceptions in terms of hardware exceptions, and lots of kernel mode code is executed in environments where exceptions are not allowed to be thrown. Also, all the implicit code generated by c++, being implicit, cannot be wrapped in #pragma directives to guarantee its placement in pageable, or non pageable memory.
As a result, C++ is not possible for kernel development on any platform at all, and generally shunned by daemon developers too. Even if one's code is written using the proper smart memory management classes and does not leak - keeping on top of potential memory fragmentation issues makes languages where memory allocation is explicit a preferred choice.
I would recommend whichever you feel more comfortable with. If you are more comfortable with C++, your code is going to be cleaner, and run more efficiently, as you'll be more used to it, if you know what I mean.
The same applies on a larger scale to something like a Python vs Perl discussion. Whichever you are more comfortable with will probably produce better code, because you'll have experience.
I think the reason is that ANSI C is the standard programming language in Linux. It is important to follow this standard whenever people want to share their code with others etc. But it is not a requirement if you just want to write something for yourself.
You personally can use C or C++ and the result will be identical. I think you should choose C++ if you know it well and can exploit some special object oriented features of it in your code. Don't look too much to other people here, if you are good in C++ just go and write your daemon in C++. I would personally write it in C++ as well.
You're right. The reason for not using C++ is KISS, particularly if you ever intend for someone else to maintain your code down the road. Most folks that I know of learned to write daemons from existing source or reading books by Stevens. Pretty much that means your examples will be in C. C++ is just fine, I've written daemons in it myself, but I think if you expect it to be maintained and you don't know who the maintainer might be down the road it shows better foresight to write in C.
Boost makes it incredibly easy to write single threaded, or multi-threaded and highly scalable, networking daemons with the asio library.
I would recommend using C++, with a reservation on using exception handling and dynamic RTTI. These features may have run time performance cost implications and may not be supported well across platforms.
C++ is more modular and maintainable so if you can avoid these features go ahead and use it for your project.
Both C and C++ are perfectly suited for the task of writing daemons.
Besides that, nowadays, you should consider also scripting languages as Perl or Python. Performance is usually just good enough and you will be able to write applications more robust and in less time.
BTW, take a look at ACE, a framework for writting portable network applications in C++.
C and C++ are different languages, blababla we know that.
But if those language are different, why is it still possible to use function like malloc or free ? I'm sure there are all sort of dusty things C++ has because of C, but since C++ is another language, why not remove those things to make it a little less bloat and more clean and clear ?
Is it because it allows programmers to work without the OO model or because some compilers doesn't support high-level abstract features of C++ ?
Because C++ would be right out dead if it wouldn't be compatible to C the way it is now. No one, except the fanbois, would like C++ if it wouldn't be compatible to C. (I know I'm probably going to be downvoted for this. Be it so!).
About "Why there's no "pure" C++ language... Well, there is at least one. The most popular one is called D, it's great, well-designed, feature-rich, pleasant to code with, and you can use C libraries with it.
Ah, and almost nobody uses it. :)
The direct reason is that C++ is not bad enough to give people a good reason to port millions of lines of their legacy code to more modern, and as you described, "pure" languages like D.
Most operating systems expose a C API, so if you want to use C++ for systems programming, you need some level of C interoperability.
That the C standard library was incorporated into the C++ standard library has historical and practical reasons: C++ began its life as an extension of C, and the C standard library was ready to use. It would be silly to exclude part of the library (like malloc and free) just because there are more idiomatic C++ alternatives: if you want to do stupid things, C++ gives you the power to do so.
For actual language semantics, the same applies - but to a lesser degree - and because of backwards-compatibility, C++ can never be entirely free of its C heritage.
It's designed so that you can port C code and compile it as C++ code directly, and it allows for incremental upgrading of existing code. If C++ didn't have malloc/free, you couldn't compile existing C code as C++, because you'd have to pay some poor shmuck to go through and find all the malloc calls and replace them, which is expensive.
C++ was designed to be compatible with C -- in fact it was originally a superset of C, but the C language has since changed to break that.
This means that C libraries -- including the C run-time library -- can be called from C++ code. It does not mean that it is a good idea to do so!
If you want a "pure" C++ then you can just use C++ without calling any C libraries.
[As others have said since I started typing this: The Design & Evolution of C++ is a good place to start reading for the background on this.]
I suggest you take a look at The Design & Evolution of C++ to get a better feel for the reason the language turned out the way it is. There are historical reasons why C++ grew out of C and was made backward compatible with it.
The early versions of C++ were built on top of C and in fact the compiler translated C++ code to C which was in turn compiled by the local C compiler. Bjarne Stroustrup is a great believer in backwards compatibility and would, I'm sure, resist any attempt to take functionality away.
You can read all about in in Bjarne's book The Design and Evolution of C++.
There were plenty of more pure languages. They didn't get widely used, though, because they were too far outside the comfort range of most programmers. C++, on the other hand, allowed programmers to slowly ramp up by allowing C styles.
What you're doing is looking at languages like C# or Python and wondering why C++ doesn't look like them, but forgetting that getting there required stepping stones like C++ and Java, or Awk and Perl.
To adapt a quotation I heard earlier: C# is Microsoft's version of Sun's for-idiots version of Bell's version of C-enhanced-by-Simula.
All are right. To sum up: the reason is politics. If you want something to be popular, enhance something already popular and you have a ready market. Design something new and no one will be interested unless you are Sun, design some utter crap, but throw billions of dollars into library development and marketing.
malloc() and free() are required so that you can call into C language libraries from C++ code. The C language library might return a pointer to memory allocated with malloc() that must be freed by the caller with free(); or, less commonly, it might require a pointer to memory allocated with malloc() that it can internally reallocate with realloc() or free with free().
I think I have an advanced knowledge of C++, and I'd like to learn C.
There are a lot of resources to help people going from C to C++, but I've not found anything useful to do the opposite of that.
Specifically:
Are there widely used general purpose libraries every C programmer should know about (like boost for C++) ?
What are the most important C idioms (like RAII for C++) ?
Should I learn C99 and use it, or stick to C89 ?
Any pitfalls/traps for a C++ developer ?
Anything else useful to know ?
There's a lot here already, so maybe this is just a minor addition but here's what I find to be the biggest differences.
Library:
I put this first, because this in my opinion this is the biggest difference in practice. The C standard library is very(!) sparse. It offers a bare minimum of services. For everything else you have to roll your own or find a library to use (and many people do). You have file I/O and some very basic string functions and math. For everything else you have to roll your own or find a library to use. I find I miss extended containers (especially maps) heavily when moving from C++ to C, but there are a lot of other ones.
Idioms:
Both languages have manual memory (resource) management, but C++ gives you some tools to hide the need. In C you will find yourself tracking resources by hand much more often, and you have to get used to that. Particular examples are arrays and strings (C++ vector and string save you a lot of work), smart pointers (you can't really do "smart pointers" as such in C. You can do reference counting, but you have to up and down the reference counts yourself, which is very error prone -- the reason smart pointers were added to C++ in the first place), and the lack of RAII generally which you will notice everywhere if you are used to the modern style of C++ programming.
You have to be explicit about construction and destruction. You can argue about the merits of flaws of this, but there's a lot more explicit code as a result.
Error handling. C++ exceptions can be tricky to get right so not everyone uses them, but if you do use them you will find you have to pay a lot of attention to how you do error notification. Needing to check for return values on all important calls (some would argue all calls) takes a lot of discipline and a lot of C code out there doesn't do it.
Strings (and arrays in general) don't carry their sizes around. You have to pass a lot of extra parameters in C to deal with this.
Without namespaces you have to manage your global namespace carefully.
There's no explicit tying of functions to types as there is with class in C++. You have to maintain a convention of prefixing everything you want associated with a type.
You will see a lot more macros. Macros are used in C in many places where C++ has language features to do the same, especially symbolic constants (C has enum but lots of older code uses #define instead), and for generics (where C++ uses templates).
Advice:
Consider finding an extended library for general use. Take a look at GLib or APR.
Even if you don't want a full library consider finding a map / dictionary / hashtable for general use. Also consider bundling up a bare bones "string" type that contains a size.
Get used to putting module or "class" prefixes on all public names. This is a little tedious but it will save you a lot of headaches.
Make heavy use of forward declaration to make types opaque. Where in C++ you might have private data in a header and rely on private is preventing access, in C you want to push implementation details into the source files as much as possible. (You actually want to do this in C++ too in my opinion, but C makes it easier, so more people do it.)
C++ reveals the implementation in the header, even though it technically hides it from access outside the class.
// C.hh
class C
{
public:
void method1();
int method2();
private:
int value1;
char * value2;
};
C pushes the 'class' definition into the source file. The header is all forward declarations.
// C.h
typedef struct C C; // forward declaration
void c_method1(C *);
int c_method2(C *);
// C.c
struct C
{
int value1;
char * value2;
};
Glib is a good starting point for modern C and gets you used to concepts like opaque types and semi-object orientation, which are common stylistically in modern C. On the other end of the spectrum standard POSIX APIs are kind of "classical" C.
The biggest gap in going from C++ to C isn't syntax, it's idiom and there, like C++, there are different schools of programming. You'll write fairly different C if you doing a device driver vs., say, an XML parser.
Q5. Anything else useful to know?
Buy a copy of K&R2 and read it through. On a cost per page basis it'll probably be the most expensive book on computing you'll ever buy with your own money but it will give you a deep appreciation for C and the thought processes that went into it. Doing the exercises will also hone your skills and get you used to what is available in the language as opposed to C++.
Taking your questions in order:
Unfortunately, there's nothing like Boost for C.
Nothing that's really on the order of RAII either.
The only compiler that tries to implement C99 is Comeau.
Lots of them all over the place, I'm afraid.
Quite a bit. C takes quite a different mindset than C.
Some of those may seem rather terse, but such is life. There are some good libraries for C, but no one place like Boost that they've been collected together or given a relatively uniform interface like Boost has done for C++.
There are lots of idioms, but many of them are in how you edit your code, such as sort of imitating RAII by writing an fopen() and a matching fclose() in quick succession, and only afterwards writing the code in between to process the data.
The pitfalls/traps that wait around every corner mostly stem from lack of dynamic data structures like string and vector, so you frequently have to write such things yourself. Without operator overloading, constructors, etc., it's considerably more difficult to make them really general purpose. Lots of libraries have them, but you end up rolling your own anyway because:the library doesn't do quite what you want, orusing the library is more work than it's worth.
The difference in mindset is almost certainly the biggest thing, at least for me. When I'm writing C++, I concentrate almost all my real effort on designing the cleanest possible interfaces, and I tend to treat the implementation of an interface as almost throwaway code. For the most part, I don't plan on making minor tweaks to that part of the code -- as long as the interface is good, replacing the entire implementation is usually easy enough that I don't worry about it much.
In C, it seems (at least to me) much more difficult to separate the interface from the implementation nearly as thoroughly or cleanly. As such, I tend to spend a lot more time trying to implement every part of the code as cleanly as possible, because later changes tend to be more difficult and throwing away and replacing pieces that aren't very good is substantially less likely to work out very well.
Edit (since people have raised questions about C99 support): While my statement about lack of C99 support may seem harsh, the fact is that it's true.
MS VC++: supports C95, and has a couple C99 features (e.g. C++ style comment delimiters), mostly because C99 standardized what they'd previously had as an extension.
Gnu: According to C99 Features Status page, the most recent iteration of gcc (4.4) has some C99 features, but some (including VLAs) are characterized as "broken", and others as "missing". Some of the missing "features" are really whole areas, not individual features.
PCC: The PCC site claims C99 conformance only as a goal for the future, not as a present reality.
Embarcadero Technologies (nee Borland) don't seem to say anything about conformance with C99 at all -- from the looks of things, the last time they worked on the C compiler may well have been before C99 was even released.
Microsoft openly states that they have no current plans for supporting C99, and they're not going to even consider it until VS 2010 is released. Though I can't find any public statements about it, Embarcadero appears about the same: no hint of a current plan, and nor even that they're going to consider working on it anytime soon.
While gcc and pcc both seem to have plans, they're currently just that: plans. They both openly admit that at the present time, they aren't really even very close to conforming with C99.
Here's a quick reference of some of the major things you'll want to know.
This is advice you didn't ask for: I think most potential employers take it as a given that if you C++ you know C. Learning the finer points of C, while an interesting academic exercise, will IMO not earn you a lot of eligibility points.
If you ever end up in a position of needing to do C, you'll catch on to the differences quickly enough.
But don't listen to me. I was too lazy and stupid to learn C++ :)
Anything else useful to know ?
C99 is not subset of c++ any revision, but separate language.
Just about the biggest shock I had when I went back to C was that variables are defined at the function level - i.e. you can't scope variables inside a block(if statement or for loop) inside a function.
Except for very few cases, any C code is valid C++, so there isn't actually anything new you should learn.
It's more a matter of unlearning.
Not using new, not using classes, defining variables at the beginning of a code block, etc.
In a strict sense, C++ is not object-oriented, but it's still procedural with support for classes. That said, you are actually using procedural programming in C++ already, the most shocking change will be not having classes, inheritance, polymorphism, etc.
As C++ is almost a superset of C89, you should know just about all of C89 already. You probably want to concentrate on the differences between C89 and C99.
I noticed some not so old VM languages like Lua, NekoVM, and Potion written in C.
It looked like they were reimplementing many C++ features.
Is there a benefit to writing them in C rather than C++?
I know something about Lua.
Lua is written in pure ANSI Standard C and compiles on any ANSI platform with no errors and no warnings. Thus Lua runs on almost any platform in the world, including things like Canon PowerShot cameras. It's a lot harder to get C++ to run on weird little embedded platforms.
Lua is a high-performance VM, and because C cannot express method calls (which might be virtual or might not) and operator overloading, it is much easier to predict the performance of C code just by looking at the code. C++, especially with the template library, makes it a little too easy to burn resources without being aware of it. (A full implementation of Lua including not only VM but libraries fits in 145K of x86 object code. The whole language fits even in a tiny 256K cache, which you find at L2 on Intel i7 and L1 on older chips. Unless you really know what you're doing, it's much harder to write C++ that compiles to something this small.)
These are two good reasons to write a VM in C.
It looked like they were reimplementing many C++ features.
Are you suggesting it's easier to implement polymorphism in C++ rather than C? I think you are greatly mistaken.
If you write a VM in C++, you wouldn't implement polymorphism in terms of C++'s polymorphism. You'd roll your own virtual table which maps function names to pointers, or something like that.
People are used to C. I have to admit that I'm more likely to write C for my own projects, even though I've been writing C++ since cfront 1.0.
If you want complete control over things, C is a little easier.
One obvious answer is interoperability. Any time language X has to call functions defined in language Y, you usually make sure that either X or Y is C (the language C, that is)
C++ doesn't define an ABI, so calling C++ code from another language is a bit tricky to do portably. But calling C code is almost trivial. That means that at least part of your VM is probably going to have to be written in C, and then why not be consistent and write the entire thing in C?
Another advantage of C is that it's simple. Everyone can read it, and there are plenty of programmers to help you write it. C++ is, for good and bad, much more of an experts language. You can do a lot of impressive things in C++, and it can save you a lot of work, but there are also fewer programmers who are really good at it.
It's much harder to be "good" at C++, and until one is good at it they will have a lot of bugs and problems. Now, especially when working on large projects with many people, the chance that one of them won't be good enough is much bigger, so coding the project in C is often less risky. There are also portability issues - C code is much easier to port across compilers than C++.
Lua also has many features that are very easy to implement in Lisp, so why doesn't it take that as a basis? The point is that C is little more than glorified assembler code with only a thin layer of abstraction. It is like a somewhat polished blank slate, on which you can build your higher level abstractions. C++ is such a building. Lua is a different building, and if it had to use C++ abstractions, it would have to bend its intent around the existing C++ structure. Starting from the blank slate instead gives you the freedom to build it like you want.
In many cases, code in C could be much faster than C++. For instance most of the functions in the stdio.c library are faster than iostream. scanf is faster than cin, printf is faster than cout etc.
and VMs demand high performance, so C code makes perfect sense, although the programs would most probably take longer to develop.
C++ is implemented in C. I suspect everyone was following the C++ approach.
Even though modern C++ compilers skip (or conceal) the explicit C++ to C translation as a discrete step, the C++ language has peculiarities that stem from the underlying C implementation.
Two examples.
Pointers in addition to references is entirely because of C. References are sufficient, and that's the way Java, Python and Ruby all work.
The classes are not first-class objects that exist at run-time because the class is only a way to define the attributes and method functions in the underlying C code. Class objects exist at run-time in Java, Python and Ruby, and can be manipulated.
Just a side note, you should look into CLR (Rotor-incarnation) and Java sources and you will note it is far more C++-as-C rather than modern or good C++. So it has a parallel there and it is a side-effect of abstracting for toys and making it average-performance happy for the crowd in managed languages.
It also helps avoid pitfalls of naive C++ usage. Exceptions and all other sort of things (bits David at boost consulting kicked off and more while we build sequencers and audio sampling before he even had a job :) are an issue too..
Python integration is another matter, and has a messy history in boost for example.. But for primitive data types and interfaces/interop and machine abstraction, well it is quite clear nothing beats C. No compiler issues either, and it still bootstraps many things before you get to anything as influential as it is/was/will be.
Stepanov recognised this achievement when he nailed STL, and Bjarne nailed it with templates.. Those are the three things always worth thinking about, as you don't have a decent incarnation of them in popular managed languages, not to that expressivness and power. All of that more than 20 years later, which is remarkable and all still bootstrap via C/C++.. Legacy of goodness (but I'm not defending 'dark age' C code c1982-2000, just the idea, yuo can misuse anything ).
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Although people seem to like to complain about C++, I haven't been able to find much evidence as to why you would want to choose C over C++. C doesn't seem to get nearly as much flak and if C++ has all these problems why can't you just restrict yourself to the C subset? What are your thoughts/experience?
Joel's answer is good for reasons you might have to use C, though there are a few others:
You must meet industry guidelines, which are easier to prove and test for in C
You have tools to work with C, but not C++ (think not just about the compiler, but all the support tools, coverage, analysis, etc)
Your target developers are C gurus
You're writing drivers, kernels, or other low-level code
You know the C++ compiler isn't good at optimizing the kind of code you need to write
Your app not only doesn't lend itself to be object-oriented but would be harder to write in that form
In some cases, though, you might want to use C rather than C++:
You want the performance of assembler without the trouble of coding in assembler (C++ is, in theory, capable of 'perfect' performance, but the compilers aren't as good at seeing optimizations a good C programmer will see)
The software you're writing is trivial, or nearly so - whip out the tiny C compiler, write a few lines of code, compile and you're all set - no need to open a huge editor with helpers, no need to write practically empty and useless classes, deal with namespaces, etc. You can do nearly the same thing with a C++ compiler and simply use the C subset, but the C++ compiler is slower, even for tiny programs.
You need extreme performance or small code size and know the C++ compiler will actually make it harder to accomplish due to the size and performance of the libraries.
You contend that you could just use the C subset and compile with a C++ compiler, but you'll find that if you do that you'll get slightly different results depending on the compiler.
Regardless, if you're doing that, you're using C. Is your question really "Why don't C programmers use C++ compilers?" If it is, then you either don't understand the language differences, or you don't understand the compiler theory.
I like minimalism & simplicity.
Because they already know C
Because they're building an embedded app for a platform that only has a C compiler
Because they're maintaining legacy software written in C
You're writing something on the level of an operating system, a relational database engine, or a retail 3D video game engine.
Fears of performance or bloat are not good reason to forgo C++. Every language has its potential pitfalls and trade offs - good programmers learn about these and where necessary develop coping strategies, poor programmers will fall foul and blame the language.
Interpreted Python is in many ways considered to be a "slow" language, but for non-trivial tasks a skilled Python programmer can easily produce code that executes faster than that of an inexperienced C developer.
In my industry, video games, we write high performance code in C++ by avoiding things such as RTTI, exceptions, or virtual-functions in inner loops. These can be extremely useful but have performance or bloat problems that it's desirable to avoid. If we were to go a step further and switch entirely to C we would gain little and lose the most useful constructs of C++.
The biggest practical reason for preferring C is that support is more widespread than C++. There are many platforms, particularly embedded ones, that do not even have C++ compilers.
There is also the matter of compatibility for vendors. While C has a stable and well-defined ABI (Application Binary Interface) C++ does not. The ABI in C++ is more complicated due to such things as vtables and constructurs/destructors so is implemented differently with every vendor, and even versions of a vendors toolchain.
In real-terms this means you cannot take a library generated by one compiler and link it with code or a library from another which creates a nightmare for distributed projects or middleware providers of binary libraries.
I take the other view: why use C++ instead of C?
The book The C Programming Language (aka: K&R) tells you clearly how to do everything the language can do in under 300 pages. It's a masterpiece of minimalism. No C++ book even comes close.
The obvious counterargument is that the same could be said of most, if not all, modern languages -- they also can't tell you how to do everything in only a few hundred pages. True. So why use C++ instead? Feature richness? Power? If you need something more feature rich or powerful then go with C#, Objective C, Java, or something else like that. Why burden yourself with the complexities of C++? If you need the degree of control C++ grants then I argue to use C. C can do anything and can do it well.
I choose to write in C because I enjoy working with a small, tight language. I like having access to a standard which can be read in a reasonable amount of time (for me -- I'm a very slow reader). Moreover, I use it to write software for embedded systems for which few desirable C++ compilers exist (like some PIC micro-controllers).
In addition to several other points mentioned already:
Less surprise
that is, it is much easier to see what a piece of code will do do exactly . In C++ you need to approach guru level to be able to know exactly what code the compiler generates (try a combination of templates, multiple inheritance, auto generated constructors, virtual functions and mix in a bit of namespace magic and argument dependent lookup).
In many cases this magic is nice, but for example in real-time systems it can really screw up your day.
I'm used to use C++ for my projects. Then I got a job where plain C is used (a 20 year old evolving codebase of an AV software with poor documentation...).
The 3 things I like in C are:
Nothing is implicit: you see what your program exactly does or not does. This makes debugging easier.
The lack of namespaces and overloads can be an advantage: if you want to know where a certain function is called, just grep through the source code directory and it will tell you. No other special tools needed.
I rediscovered the power of the function pointers. Basically they allow you to do all polymorphic stuff you do in C++, but they are even more flexible.
Linus' answer to your question is "Because C++ is a horrible language"
His evidence is anecdotal at best, but he has a point..
Being more of a low level language, you would prefer it to C++..C++ is C with added libraries and compiler support for extra features (both languages have features the other language doesn't, and implement things differently), but if you have the time and experience with C, you can benefit from extra added low level related powers...[Edited](because you get used to doing more work manually rather than benefit from some powers coming from the language/compiler itself)
Adding links:
Why C++ for embedded
Why are you still using C? PDF
I would google for this.. because there are plenty of commentaries on the web already
Because they're writing a plugin and C++ has no standard ABI.
Long compile times can be annoying. With C++ you can have very long compile times (which means, of course, more time for Stack Overflow!).
If you want your code to be understood by virtually any programmer write in C.
I'm surprised no one's mentioned libraries. Lots of languages can link against C libs and call C functions (including C++ with extern "C"). C++ is pretty much the only thing that can use a C++ lib (defined as 'a lib that uses features in C++ that are not in C [such as overloaded functions, virtual methods, overloaded operators, ...], and does not export everything through C compatible interfaces via extern "C"').
Because they want to use features in C99 that don't have equivalents in C++.
However, there aren't as many C99 features that are useful to C++ as people think at first glance. Variable-length arrays? C++ has std::vectors. Support for complex/imaginary numbers? C++ has a templated complex type. Type-generic math functions? C++ overloaded the standard math functions, causing the same result.
Named initializers? Not in C++, but there's a workaround:
struct My_class_params {
int i;
long j;
std::string name;
My_class_params& set_i(int ii)
{
i = ii;
return *this;
}
My_class_params& set_j(long jj)
{
j = jj;
return *this;
}
template <typename STRING>
My_class_params& set_name(STRING&& n)
{
name = std::forward<STRING>(n);
return *this;
}
My_class_params()
{
// set defaults
}
};
class My_class {
My_class_params params;
public:
My_class(const My_class_params& p) : params(p) { }
...
};
This allows you to write things like:
My_class mc(My_class_params().set_i(5).set_name("Me"));
This is pretty shallow but as a busy student I chose C because I thought C++ would take too long to learn. Many professors at my university won't accept assignments in Python and I needed to pick up something quickly.
Because for many programming tasks C is simpler, and good enough. When I'm programming lightweight utilities especially, I can feel like C++ wants me to build in an elegant supersructure for its own sake, rather than simply write the code.
OTOH, for more complex projects, the elegance provides more good solid structural rigor than would naturally flow out of my keyboard.
Most of the significant features of c++ somehow involve classes or templates. These are wonderful features except for the way the compiler transforms these into object code. Most compilers use name mangling, and the ones that don't do something at least as messy.
If your system lives on its own, as is the case with many applications, then C++ is a fine choice.
If your system needs to interact with software not neccesarily written in C++ (most frequently in assembler, or Fortran Libraries) then you are in a tight spot. To interact with those kinds of cases, you'll need to disable name mangling for those symbols. this is usually done by declaring those objects extern "C", but then they can't be templates, overloaded functions, or classes. If those are likely to be your applications API, then you'll have to wrap them with helper functions, and keep those functions in sync with the actual implementations.
And in reality, the C++ language provides a standard syntax for features that can be easily implemented in pure C.
In short, the overhead of interoperable C++ is too high for most folks to justify.
Oh my, C vs C++, a great way to start a flame war. :)
I think C is better for driver and embedded code.
C++ has some great features that C doesn't have, but many of the object oriented features of C++ can cause monumental coding messes when people write code with non-obvious side-effects that occur behinds the scenes. Crazy code can be hidden in constructors, destructors, virtual functions, ... The beauty of C code is the language does nothing non-obvious behind your back, thus you can read the code and not have to look up at every constructor and destructor and so on. A lot of the problem is bad coding practices by SOME people.
My perfect language would be a combination of C99 plus a minimal subset of safer C++ capabilities that adds ZERO (or near zero) compiler overhead to the binary output. Perfect additions would be class encapsulation and naming concepts of data and functions.
One remark about "just use the subset of C++ you want to use": the problem with this idea is that it has a cost to enforce that everybody in the project uses the same subset. My own opinion is that those costs are quite high for loosely coupled projects (e.g. open source ones), and also that C++ totally failed at being a better C, in the sense that you cannot use C++ wherever you used C.
I haven't been able to find much evidence as to why you would want to choose C over C++.
You can hardly call what I'm about to say evidence; it's just my opinion.
People like C because it fits nicely inside the mind of the prgrammer.
There are many complex rules of C++ [when do you need virtual destructors, when can you call virtual methods in a constructor, how does overloading and overriding interact, ...], and to master them all takes a lot of effort. Also, between references, operator overloading and function overloading, understanding a piece of code can require you to understand other code that may or may not be easy to find.
A different question in why organizations would prefer C over C++. I don't know that, I'm just a people ;-)
In the defense of C++, it does bring valuable features to the table; the one I value most is probably parametric('ish) polymorphism, though: operations and types that takes one or more types as arguments.
I would say that C gives you better control over optimization and efficiency than C++ and hence would be useful in situations where memory and other resources are limited and every optimization helps. It also has a smaller footprint of course.
There's also the approach some shops take of using some of C++'s features in a C-like way, but avoiding ones that are objectionable. For example, using classes and class methods and function overloading (which are usually easy for even C diehards to cope with), but not the STL, stream operators, and Boost (which are harder to learn and can have bad memory characteristics).
Because you're writing for a system where resources are tight (such as an embedded system, or some kind real bare metal code like a kernel) and you want as little overhead as possible.
There's a reason why most embedded systems don't have a C++ compiler - it's not that people don't want one, it's that cramming C++ code into that small a space is task that approaches impossible.
Until some years ago the existing C++ compilers were missing important features, or the support was poor and the supported features vary wildly among them, and so it was hard to write portable applications.
Because of the no standard naming of symbols it is difficult for other languages/applications to support C++ classes directly.
What C needed was a better preprocessor.
cfront was one and thus born c++
I'ld use C, where the 'c++ as preprocessor' would not be okay.
I'm pretty sure, at the bottom of any well written c++ library/framework/toolkit,
you would find dirty-old-c ( or static casts, which is same )