Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C and C++: A Case for Compatibility


August 2002/C and C++: A Case for Compatibility

C and C++: A Case for Compatibility

Bjarne Stroustrup

Bjarne identifies some non-issues as he continues his case for compatibility between C and C++.


Modern C [1, 2] and C++ [3] are sibling languages [4, 5] descended from Classic C [6]. In many people’s minds, they are (wrongly, but understandably) fused into the mythical C/C++ programming language. There is no C/C++ language, but there is a C/C++ community. In last month’s CUJ, I described some of the incompatibilities that complicate the work of developers within that C/C++ community. In this article, I’ll discuss some of the underlying myths that help perpetuate these incompatibilities. I’ll also show why more compatibility (ideally, full compatibility) is in the best interest of the C/C++ community. Next month, I’ll present some examples of how the incompatibilities in C and C++ might be resolved.

Red Herrings

Given the shared history of C and C++ and the many similarities between the languages, one might wonder why C and C++ are not fully compatible now. There are some good (though, ultimately, answerable) arguments for incompatibility (see sidebar), but the debate is often clouded by a few popular misconceptions about the differences between C and C++. These red herring arguments confound and inflame debates about C/C++ compatibility. What these arguments have in common is that they subtly and indirectly mischaracterize one or both of the languages, thus diverting the debate from compatibility to a discussion about the value of some aspect of one of the languages. These red herrings are divisive and often irrelevant because compatibility is valuable even if some individual language features are undesirable.

The ten red herrings of C/C++ compatibility are:

  1. C++ is object-oriented, I don’t like object-oriented programming, so I have no use for C++. This statement ignores the fact that large parts of C++ are not there to support OOP. (In this context, OOP is most often interpreted as programming using class hierarchies.) Other parts of C++ focus on features such as stronger type checking, const in constant expressions, new and delete, function overloading, and templates. C++ supports OOP, but it makes no attempts to impose that style. A significant part of C++’s success comes from not abandoning traditional C styles of programming where they are considered appropriate. In particular, suggesting the greatest possible degree of C/C++ compatibility is (emphatically) not suggesting that every program should be structured as a set of class hierarchies.
  2. I don’t do low-level programming, so I have no use for C. This would have been a strong argument had C++ been consistently used as a high-level language only. However, most major C++ programs have components that simply couldn’t be written in C++ had C++ not supported efficient close-to-the-hardware programming. Many of these facilities are similar to or identical to what C offers. After all, C++ was deliberately designed to support C-style low-level programming.
  3. I just need a simple language. We all do. However, we need a language that is simple for what we do. Different people have significantly different needs and significantly different opinions on what makes a language simple. Neither C nor C++ can be considered simple without fairly contorted explanations and apologetic references to history. Simplicity in any abstract or absolute sense is not among the reasons for the success of C and C++, and neither C nor C++ will become any simpler in the future. The real question is whether C and C++ users have to deal with convergent or divergent evolution of these languages. Some people use “a simple language” to mean C, which is clearly a simpler language than C++. However, there is no reason to believe that the simplest expression of a given problem will use all the facilities of C. Nor is there any reason to believe that the set of facilities providing the simplest, most elegant, and most efficient solution will come from C only. One result of C++ being a larger language is that we can often express a simpler solution for a given problem using C++ than is possible using C only.
  4. But we don’t need those features. This argument is often heard from both C and C++ proponents. Typical examples of features mentioned as “not wanted” are casts and virtual functions. No individual programmer needs every feature of C or C++ every day or in every project. However, the set of features needed by an organization or by a programmer over the time span of a few years starts to approach the set of features provided. For C++, this is particularly true when you take into account the facilities used by developers of sophisticated libraries. Also, essentially all programmers wish for “just one little extension, well, maybe two” and often have good reasons.
  5. C++ is too slow. There are C++ libraries that are slow and/or take up too much space. However, this is not an inherent property of the C++ language or of the current implementations of C++. You have slow and bloated libraries in any language, including C. When I hear the “efficiency” argument, I confidently suggest measurements. Generally, C++ is fast enough for high-level features to be used in applications demanding high performance (such as classes and templates in matrix applications competing with Fortran [7, 8, 9]). When the high-level features are not fast enough or not flexible enough, we can always do as well in C++ as we could in C by using the low-level feature shared with C.
  6. C and C++ are fundamentally different languages. This argument is either a troll or a statement from someone with a very narrow notion of “fundamentally different.” The differences in the parts of the languages supporting traditional C programming are minor and arose from historical accident [4, 5]. For a really different language, have a look at just about any language that isn’t C or C++, such as ML, Python, Smalltalk, Ada, Prolog, or Scheme.
  7. C++ would be much better if it weren’t for C compatibility. Some improvements could probably be made to C++ if C compatibility wasn’t an issue: C-style casts, narrowing conversions, and the structure tag namespace spring to mind. However, even if C and C++ each goes its own way, there already exists so much C++ code that a thorough cleanup is impossible. And anyway, the highest degree of C/C++ compatibility that doesn’t interfere with C++’s abstraction mechanisms is a design aim. The opposite claim: “C would be much better if it wasn’t for C++ compatibility” has been made, but far less frequently. After all, the parts of C borrowed from C++ are far fewer and less central to C than the C parts are to C++.
  8. C is simpler than C++, so C compilers are better than C++ compilers. This is no longer true for the major C++ suppliers. Their C and C++ compilers are different options on the same compiler, relying on the same optimizers, linkers, etc. This “simpler compiler” argument can be valid only in markets where no C++ compiler exists. With high-quality commercial and free C++ front ends available and back ends largely language neutral, this is less of a concern than it once was.
  9. C is small and understandable; C++ isn’t. C is smaller than C++ and easier to learn if by learning you mean gaining an understanding of most language features. However C is not small; old-timers tend to forget their initial efforts and to seriously underestimate how much has been added. The C99 Standard is 550 pages long. Few people understand all of C. Fortunately, with C as with C++, few people need to understand the whole language. What takes extra time learning C++ compared to learning C is primarily learning new programming techniques. If you know object-oriented programming or generic programming, learning the C++ facilities is relatively easy. If not, learning those new programming techniques using C++ can decrease the total learning time compared to using C. It is relatively easy to learn a useful amount of C++, even compared to learning sufficient C to complete similar tasks [10]. C is not the ideal subset of C++ from a teaching/learning perspective, nor from a utility or efficiency point of view. Only a lack of compatibility stops people from choosing more ideal subsets.
  10. If you want C++ features, just use C++. For many programmers, this misses the point. They can’t just pick and choose among languages based on the need of a feature or two. Usually a language is chosen for a project, and most often that language isn’t changed out of fear of real and imagined conversion problems. One of the key problems with incompatibilities — even incompatibilities that don’t reflect differences in basic functionality — is that they provide a barrier to experimentation and to the evolution of programs. Often, a language is chosen for a project based on little knowledge of the future task, mostly on a couple of programmers’ previous experiences, and on what happens to be available. However, because of incompatibilities, that choice is still binding for different programmers years later after all the tools and even the language standards have changed.

Benefits of C/C++ Compatibility

In the absence of specific arguments against, compatibility is obviously preferable to incompatibility. Logically, it is the task of whoever proposes an incompatibility to demonstrate its value. However, we don’t have a clean slate. C is now about 28 years old, and C++ about 18 years. History is important, and increasing the degree of compatibility implies cost and so requires argument. Therefore, it is worth stating the benefits of compatibility as they are today.

The basic argument for compatibility is that it maximizes the community of contributors. Each dialect and incompatibility limits:

  • The size of the market for vendors/suppliers/builders.
  • The set of available libraries and tools for users.
  • The set of possible collaborators (suitable employees, students, consultants, experts, etc.) for projects.

A larger community is a disproportionate advantage. For example, a community of size N provides more than twice the benefits of a community of size N/2. The reason is better communication — and less replicated work.

C and C++ are clearly closely related historically, but why should we look to C/C++ compatibility for benefits? After all, we don’t worry about C/Fortran compatibility or C++/Java compatibility. The difference is that C and C++ have a huge common subset, and there exists a C/C++ community, sharing:

  • Fundamental concepts and constructs leading to shared teaching and learning.
  • Libraries based on common declarations and data layout.
  • Tools, including compilers.

Once you know C or C++, you know a significant part of the other language. With a few exceptions, the statement and expression syntax, the basic types, the semantics, and the ways of composing programs out of functions and translation units are shared, so are many basic programming techniques. This commonality is more than skin deep; it is not just a syntactic similarity hiding major underlying differences. If something looks the same, it usually means the same thing, has the same basic performance characteristics, and can be used unchanged in or from the other language. Features that are similar, but different, in each language (such as void*, bool, and enumerations [5]) are a burden for teachers and students. For novices, the differences magnify as obstacles to understanding and give rise to myths about their origins and purposes.

These problems persist beyond the initial learning. There are many C++ programmers who have never compiled a C source file, but how many C++ programs don’t call a C library? If a C library is used directly, the programmer must understand the constructs appearing in its header files. Even if C code is used only indirectly, some aspects of C must often be taken into account, such as C’s use of malloc rather than new, the use of arrays rather than C++ Standard library containers, and the absence of exception handling. You’ll certainly find C programmers who have never used C++, especially embedded systems programmers who work on platforms for which a C++ compiler does not exist. But there are relatively fewer programmers for such platforms than there used to be. Many C programmers occasionally use C++ directly, and many rely on C++ libraries (accessed through C interfaces, of course).

For maintenance programmers, each incompatibility is yet another thing for the programmer to keep in mind and a source of errors. For library builders, differences require decisions about which language and dialect should be used for implementation and create a need for multiple interfaces (or a common interface using minimal features only) to support several languages and dialects. For tools builders, including compiler writers, each incompatible feature forces a special case in the implementation and often a compiler option for its control.

The advantage of compatibility is the absence of such problems. Each incompatibility adds a burden and decreases sharing. For individuals and for organizations, compatibility offers a larger universe for experimentation and for the selection of tools, language facilities, libraries, literature, and techniques.

Who benefits? Some programmers take the view that compatibility is at best a nuisance because it does not benefit the working programmer. Naturally, this view is most common among “C-only programmers” and “C++-only programmers” and rare among programmers who regularly use both C and C++. There are benefits from C/C++ compatibility for C programmers who rarely or even never use C++:

  • Being part of a larger community implies that more resources are available for tools, compilers, magazines, textbooks, etc. For example, C and C++ compilers typically share optimizers. By serving the union of C and C++ programmers on a given platform, a compiler group can afford to provide more advanced optimizations, better debuggers, etc.
  • The C/C++ community has a larger “mind share” than C alone. This implies that C is taken more serious in planning and teaching than it would have been in the absence of C++. The larger community also adds to the richness of the intellectual climate.
  • On most major platforms, C programs can and usually do benefit from being able to call libraries written in C++ (without additional call overhead or data layout conversion).

The argument applies to C++ programmers who rarely or even never use C.

On the other hand, C/C++ incompatibilities impose a burden on tools and on library implementers, who, without actually using C++, want to benefit from users in the C++ community. To allow a library to be used in both C and C++ programs, an implementer needs to know what constructs can be safely used in interfaces. (For example, don’t use a C++ keyword, such as new as a struct member, and don’t use a name from a Standard C99 header, such as csin as a global name.) To allow an implementation to be compiled as either C or C++, even more care needs to be taken, such as remembering to cast the result of malloc to the appropriate type.

There are people who believe that, if C++ would just go away, all the C++ programmers would become C programmers and the C++ libraries would become C libraries so that C++ won’t add to the size of the C/C++ community. Some people hold similarly unrealistic views on C from the C++ perspective. Neither of the two languages will go away, and the shared community is a source of strength to both languages.

What Should Be Done?

What can be done about the C/C++ incompatibilities? What should be done? I hear four basic answers:

  1. Nothing, the incompatibilities are good for you. I simply don’t believe that, having never seen a piece of code that benefited from an incompatibility in any fundamental way. However, if enough people are of that opinion, the C and C++ Standard committees will proceed to reduce the area of compatibility and to provide competing incompatible additions. That would destroy the C/C++ community. Programmers would increasingly face a choice between a language rich in built-in facilities and a language rich in abstraction facilities. Naturally, both language communities would be busy compensating for their weaknesses by providing libraries, which in turn would further increase the areas of incompatibility. The primary beneficiaries of this would be languages outside the C/C++ family.
  2. Nothing, it’s too late. Given that I consider the current level of C/C++ incompatibility a major problem with no technical or philosophical foundation, I’m most reluctant to accept that nothing can be done. However, it is possible that changes really are infeasible today. In that case, we can strive to minimize future incompatibilities and to remove incompatibilities where opportunity arises. More likely, people will draw the conclusion that compatibility is already lost, so compatibility concerns should not be allowed to complicate the design of new language features and libraries. In particular, there will be pressure for each language to provide competing, incompatible versions of popular facilities.
  3. Remove all incompatibilities. This is my ideal. I believe it is in the long-term best interest of the C/C++ community to remove all incompatibilities between C and C++. We ought to try for that. Clearly, removing incompatibilities would involve changes to both languages and compromises would have to be crafted to minimize the impact on users of both languages. Silent changes — that is, changes that are not easily diagnosed by a compiler — should be minimized. Wherever possible, the compromises should be crafted to increase the consistency of the resulting set of features and to simplify the language rules. It will be difficult to remove all incompatibilities. However, the amount of work required from the C/C++ community to reach compatibility will be far less than that required from it to live with increasingly incompatible languages.
  4. Remove most of the incompatibilities; removing all is impossible. Unfortunately, we can’t always get all we want. In that case, we should figure out which incompatibilities can be removed and get rid of those. We should also consider ways of improving interoperability, especially among libraries, in cases where source-code compatibility is deemed infeasible. After that exercise, maybe the remaining incompatibilities won’t look so impossible to remove or to live with, and maybe the exercise would discourage the growth of new incompatibilities.

I clearly value C/C++ compatibility highly. Many, many years ago, John Bentley suggested that C and C++ be gradually merged and that each year the size of the ++ in C++ should be reduced slightly until only the C was left. That was a good idea, but it didn’t happen. However, we are now at a stage in the development of C and C++ where the long-standing semi-official C++ policy of “as close to C and possible, but no closer” could become a policy of full compatibility provided the C and C++ communities so decided. If this opportunity is missed, the languages will embark on divergent evolutions, and the C/C++ community will fracture into many parts.

What would be the result of a systematic process of increasing compatibility? A single language called C or C++? Possibly, but I consider it more likely that the result would be a language called C++ with a precisely specified subset called C. I’m no fan of language subsetting, but I do respect the people who insist that something smaller than C++ is important in some application areas and in some communities. If nothing else, that approach would avoid an emotional discussion about naming.

The next article in this series will make some concrete suggestions as to how C and C++ might be changed to approach full compatibility.

References

[1] ISO/IEC 9899:1990, Programming Languages C.

[2] ISO/IEIC 9899:1999, Programming Languages C.

[3] ISO/IEC 14882, Standard for the C++ Language.

[4] Bjarne Stroustrup. Sibling Rivalry: C and C++, AT&T Labs — Research Technical Report TD-54MQZY, January 2002, <www.research.att.com/~bs/sibling_rivalry.pdf>.

[5] Bjarne Stroustrup. “C and C++: Siblings,” C/C++ Users Journal, July 2002.

[6] Brian Kernighan and Dennis Ritchie. The C Programming Language (Prentice-Hall, 1978).

[7] <http://oonumerics.org/blitz/>

[8] <www.osl.iu.edu/research/mtl>

[9] <www.acl.lanl.gov/Pooma>

[10] Bjarne Stroustrup. “Learning Standard C++ as a New Language,” C/C++ Users Journal, May 1999. Also available in CVU, Vol. 12, No. 1, January 2000.

Bjarne Stroustrup is the designer and original implementer of C++. He has been a member of the C/C++ community since he first used C in 1975. For 17 years, he worked in Bell Labs’ Computer Science Research Center alongside people such as Dennis Ritchie and Brian Kernighan. In the early 1980s, he participated in the internal Bell Labs standardization of C. He is the author of The C++ Programming Language and The Design and Evolution of C++. His research interests include distributed systems, operating systems, simulation, design, and programming. He is an AT&T Fellow and heads AT&T Lab’s Large-scale Programming Research department. He is actively involved in the ANSI/ISO standardization of C++. He received the 1993 ACM Grace Murray Hopper award and is an ACM fellow.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.