Compatibility of C and C++

From Wikipedia, the free encyclopedia
Jump to: navigation, search

The C and C++ programming languages are closely related. C++ grew out of C, as it was designed to be source-and-link compatible with C.[1] Due to this, development tools for the two languages (such as IDEs and compilers) are often integrated into a single product, with the programmer able to specify C or C++ as their source language. However, due to minor semantic differences, most non-trivial C programs will not compile as C++ code without modification — C++ is not a superset of C.[2]


Bjarne Stroustrup, the creator of C++, has suggested[3] that the incompatibilities between C and C++ should be reduced as much as possible in order to maximize inter-operability between the two languages. Others have argued that since C and C++ are two different languages, compatibility between them is useful but not vital; according to this camp, efforts to reduce incompatibility should not hinder attempts to improve each language in isolation. The official rationale for the 1999 C standard (C99) "endorse[d] the principle of maintaining the largest common subset" between C and C++ "while maintaining a distinction between them and allowing them to evolve separately", and stated that the authors were "content to let C++ be the big and ambitious language."[4]

Several additions of C99 are or were not supported in C++ or conflicted with C++ features, such as variadic macros, compound literals, designated initializers, variable-length arrays, and native complex number types. The long long int datatype and restrict type qualifier defined in C99 were not included in the C++03 standard, but most mainstream compilers such as the GNU Compiler Collection,[5] Microsoft Visual C++, and Intel C++ Compiler provided them as an extension. The long long datatype along with variadic macros are present in the new C++ standard, C++11. On the other hand, C99 has reduced some other incompatibilities by incorporating C++ features such as // comments and mixed declarations and code.[6]


One commonly encountered difference is that C allows a void* pointer to be assigned to any pointer type without a cast, whereas C++ does not; this idiom appears often in C code using malloc memory allocation.[7] For example, the following is valid in C but not C++:

void* ptr;
int *i = ptr;       /* Implicit conversion from void* to int* */

or similarly:


In order to make the code compile in C++, one must use an explicit cast:

void* ptr;
int *i = (int *) ptr;
int *j = (int *) malloc(sizeof(int) * 5);

Another portability issue from C to C++ are the numerous additional keywords that C++ introduced. This makes C code that uses them as identifiers invalid in C++. For example:

struct template 
    int new;
    struct template* class;


C++ compilers prohibit using goto or switch from crossing an initialization, as in the following C99 code:

void fn(void)
  goto flack;
  int i = 1;

There are many other C syntaxes which are invalid or behave differently in C++:[8]

  • The comma operator can result in an "l-value" (a quantity that can be used for the left-hand side of an assignment) in C++, but not in C.
  • C does not allow a given typedef to be duplicated in the same scope, whereas C++ allows repeated typedefs. Note that this is only true for C99 and before. C11 allows duplicate typedef names.[9]
  • Enumeration constants (enum values) are always of type int in C, whereas they are distinct types in C++ and may have a size different from that of int.
  • C++ also changes some C standard library functions to add additional polymorphic functions with const type qualifiers, e.g. strchr returns char* in C, while C++ acts as if there were two polymorphic functions const char *strchr(const char *) and a char *strchr(char *).
  • In both C and C++, one can define nested struct types, but the scope is interpreted differently (in C++, a nested struct is defined only within the scope/namespace of the outer struct).
  • Non-prototype ("K&R"-style) function declarations are not allowed in C++, although they have also been deprecated in C since 1990. Similarly, implicit function declarations (using functions that have not been declared) are not allowed in C++, but have also been deprecated in C since 1999.
  • A struct, union, or enum declaration in C++ usually results in an implicit typedef of the same name, while in C, it does not.
  • C++ is more strict than C about pointer assignments that discard a const qualifier (e.g. assigning a const int* value to an int* variable): in C++ this is invalid and generates a compiler error (unless an explicit typecast is used),[10] whereas in C this is allowed (although many compilers emit a warning).
  • C++ allows to use const variable in case: operator, C doesn't. Also in C++ const variable must be initialized, in C it's not necessary.
  • In C99 and above, the _Complex type exists to represent complex numbers. This data type does not currently exist at all in any standard of C++, which instead provides its own specialized class, std::complex, to represent complex numbers. Some compilers, such as GCC, provide _Complex as a C++ extension.
  • Initialization designators can be used to initialize elements of an array by index, e.g. int foo[] = { [42] = 1, [0] = -1 };


There are a few syntactical constructs that are valid in both C and C++, but produce different results in the two languages.[11]

For example, character literals such as 'a' are of type int in C and of type char in C++, which means that sizeof 'a' will generally give different results in the two languages: in C++, it will be 1, while in C it will be sizeof(int) which on architectures with 8 bit wide char will be at least 2. As another consequence of this type difference, in C, 'a' will always be a signed expression, regardless of whether or not char is a signed or unsigned type, whereas for C++ this is compiler implementation specific.

C++ implicitly treats any const global as file scope unless it is explicitly declared extern, unlike C in which extern is the default. Conversely, inline functions in C are of file scope whereas they have external linkage by default in C++.[7]


extern int T;
int size(void)
    struct T {  int i;  int j;  };
    return sizeof(T);
    /* C:   return sizeof(int)
     * C++: return sizeof(struct T)


Both C99 and C++ have a boolean type bool with constants true and false, but they behave differently. In C++, bool is a built-in type and a reserved keyword. In C99, a new keyword, _Bool, is introduced as the new boolean type. In many aspects, it behaves much like an unsigned int, but conversions from other integer types or pointers always constrained to 0 and 1. Other than for other unsigned types, and as one would expect for a boolean type, such a conversion is 0 if and only if the expression in question evaluates to 0 and it is 1 in all other cases. The header stdbool.h provides macros bool, true and false that are defined as _Bool, 1 and 0, respectively.

Linking C and C++ code[edit]


  • C compilers do not name mangle symbols in the way that C++ compilers do.[12]



/* Header file foo.h */
extern "C" {
/* These functions get C linkage */
void foo();
struct bar { /* ... */ };


For example, the following code:

void my_function();
void bar()


$ CC -c



  1. ^ Stroustrup, Bjarne. "An Overview of the C++ Programming Language" (PDF). p. 4. Retrieved 12 August 2009. 
  2. ^ "Bjarne Stroustrup's FAQ – Is C a subset of C++?". Retrieved 5 March 2014. 
  3. ^ "Bjarne Stroustrup's Homepage". Retrieved 18 August 2013. 
  4. ^ Rationale for International Standard—Programming Languages—C, revision 5.10 (April 2003).
  5. ^ Restricted Pointers from Using the GNU Compiler Collection (GCC)
  7. ^ a b "IBM Knowledge Center". 
  8. ^ David R. Tribble (Aug 2001). "Incompatibilities Between ISO C and ISO C++" (1.0 ed.). 
  9. ^ ISO9899-2011 6.7p3 bullet #1
  10. ^ "Const correctness, C++ FAQ". 4 July 2012. Retrieved 18 August 2013. 
  11. ^ "C constructs to avoid". 
  12. ^ "IBM Knowledge Center". 
  13. ^ "IBM Knowledge Center". 
  14. ^ "Oracle Documentation". Retrieved 18 August 2013. 

External links[edit]