Any technical benefits to C++ in a C project?
If you are running a large project written in C and it is decided that in future developers will be allowed to use C++, are there any C++ constructs whose use should be recommended against?
The short answer is that use of any C++ construct in existing C code should be recommended against.
The technical advantages of using C++ come about through use of its large scale code organizational features such as namespaces, classes and perhaps templates. Unless an existing C code base is restructured to use these constructs there is no real technical benefit for moving to C++; there may be non-technical reasons for allowing C++, as I wrote about recently.
My experience of projects where developers have been given permission to start using C++ within an existing C code base has not been positive. Adding namespaces/classes is a lot of work and rarely happens until a major rewrite; in the meantime C++ developers use new
instead of malloc
(which means the code now has to be compiled by a C++ compiler for a purely trivial reason). In days of old //
style comments were sometimes touted as a worthwhile benefit of using C++ (I kid you not; now of course supported by most C compilers), as was the use of inline
(even though back then few C++ compilers did much actual inlining), and what respectable programmer would use a C printf
when C++’s iostreams provided <<
(oh, if only camera phones had been available back in the day, what a collection of videos of todays experts singing the praises of iostreams I would have ;-)
There are situations where use of C++ in an existing code base makes sense. For example, if the GCC project is offered a new optimization phase written in C++, then the code will presumably have been structured to make use of the high level C++ code structuring features. There is no reason to turn this code down or request that it be rewritten just because it happens to be in C++.
Derek, I think you have missed some technical advantages of C++ over C even if you are writing to a C-style interface and use very few C++ constructs. For example, the C++ type system is stronger than C in several ways:
– C++ has a separate Boolean type (I know C’99 has a _Bool type too, but nobody is using C’99).
– C++ enums are distinct types, not synonyms for some integral type. You can’t accidentally assign a variable of an enum type a value of an integral type or another enum type.
– string literals have type const char* in C++ as opposed to char* in C, making it harder to accidentally mutate them (which is \undefined behaviour\).
– Using the C++ cast operators static_cast, const_cast and reinterpret_cast in preference to the C-style cast makes it clearer what you are trying to achieve and offers some protection against errors (e.g. you can’t accidentally cast away const-ness in a reinterpret_cast).
Also, if you declare default constructors for your structs, then you guard against failure of client code to initialise them, which is another source of undefined behaviour.
So I take the view that in principle, a C++ compiler should be used in preference to a C compiler, assuming a good C++ compiler for the target platform is available. The tricky part is to prevent developers using less desirable C++ constructs. I think that for critical software development, we need for a C++ subset that is much more restrictive than existing standards such as MISRA C++ or JSF C++, along with a tool to enforce compliance.
David, good to hear from you again. Yes the C++ type system is generally stronger than C’s, which is a good thing. But if you have an existing large code base in C and limited resources, then C++’s stronger type system may require lots of minor edits to be made for little gain. gcc’s -Wall option can be used to catch enum issues and will flag modification of string literals. When writing code for this first time the stronger C++ type system would be an advantage.
C99 might not have a strong presence in the embedded world but on more resource rich computers it is used a lot (although C is not as common on such computers).
There is a C idiom where enum values are bitwise distinct and enumeration constants are OR’ed/AND’ed and then compared to 0, something that the C++ type system will object to.
I have heard the claims about using static_cast, const_cast and reinterpret_cast. I am not aware of any source measurements showing that developers use these casts for this purpose and I wonder if there is a default kind of cast that developers use unless forced to use something else.