Where is C not a subset of C++?

C++C

C++ Problem Overview


I read in a lot of books that C is a subset of C++.

Some books say that C is a subset of C++, except for the little details.

What are some cases when code will compile in C, but not C++?

C++ Solutions


Solution 1 - C++

If you compare C89 with C++ then here are a couple of things

No tentative definitions in C++

int n;
int n; // ill-formed: n already defined

int[] and int[N] not compatible (no compatible types in C++)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

No K&R function definition style

int b(a) int a; { } // ill-formed: grammar error

Nested struct has class-scope in C++

struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)

No default int

auto a; // ill-formed: type-specifier missing

C99 adds a whole lot of other cases

No special handling of declaration specifiers in array dimensions of parameters

// ill-formed: invalid syntax
void f(int p[static 100]) { }

No variable length arrays

// ill-formed: n is not a constant expression
int n = 1;
int an[n];

No flexible array member

// ill-formed: fam has incomplete type
struct A { int a; int fam[]; }; 

No restrict qualifier for helping aliasing analysis

// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);

Solution 2 - C++

In C, sizeof('a') is equal to sizeof(int).

In C++, sizeof('a') is equal to sizeof(char).

Solution 3 - C++

C++ has new keywords as well. The following is valid C code but won't compile under C++:

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;

Solution 4 - C++

There are plenty of things. Just a simple example (it should be enough to prove C is not a proper subset of C++):

int* test = malloc(100 * sizeof(int));

should compile in C but not in C++.

Solution 5 - C++

In C++, if you declare a struct, union, or enum, its name is immediately accessible without any qualifiers:

struct foo { ... };
foo x; // declare variable

In C, this won't work, because types thus declared live in their own distinct namespaces. Thus, you have to write:

struct foo { ... };
struct foo x; // declare variable

Notice the presence of struct there on the second line. You have to do the same for union and enum (using their respective keywords), or use the typedef trick:

typedef struct { ... } foo;
foo x; // declare variable

Consequently, you can have several types of different kinds named the same in C, since you can disambiguate:

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

In C++, however, while you can prefix a struct name with keyword struct whenever you reference it, the namespaces are merged, and so the above C snippet isn't valid. On the other hand, C++ specifically makes an exception to allow a type and a typedef for that type to have the same name (obviously with no effect), to allow the use of typedef trick unchanged from C.

Solution 6 - C++

This also depends on what variety of C you're using. Stroustrup made C++ as compatible as he could, and no more compatible, with the 1989 ANSI and 1990 ISO standards, and the 1995 version changed nothing. The C committee went in a somewhat different direction with the 1999 standard, and the C++ committee has changed the next C++ standard (probably out next year or so) to conform with some of the changes.

Stroustrup lists incompatibilities with C90/C95 in Appendix B.2 of "The C++ Programming Language", Special Edition (which is 3rd edition with some added material):

'a' is an int in C, a char in C++.

The sizeof an enum is int in C, not necessarily in C++.

C++ has // comments to end of line, C doesn't (although it's a common extension).

In C++, a struct foo { definition puts foo into the global namespace, while in C it would have to be referred to as struct foo. This allows a struct definition to shadow a name in an outer scope, and has a few other consequences. Also, C allows larger scope for struct definitions, and allows them in return type and argument type declarations.

C++ is fussier about types in general. It won't allow an integer to be assigned to an enum, and void * objects cannot be assigned to other pointer types without a cast. In C, it's possible to provide an overlarge initializer (char name[5] = "David" where C will discard the trailing null character).

C89 allowed implicit int in many contexts, and C++ doesn't. This means that all functions must be declared in C++, while in C89 it was often possible to get by with assuming int for everything applicable in the function declaration.

In C, it's possible to jump from outside a block to inside using a labeled statement. In C++, this isn't allowed if it skips an initialization.

C is more liberal in external linkage. In C, a global const variable is implicitly extern, and that's not true in C++. C allows a global data object to be declared several times without an extern, but that's not true in C++.

Many C++ keywords are not keywords in C, or are #defined in standard C headers.

There are also some older features of C that aren't considered good style any more. In C, you can declare a function with the argument definitions after the list of arguments. In C, a declaration like int foo() means that foo() can take any number of any type of arguments, while in C++ it's equivalent to int foo(void).

That seems to cover everything from Stroustrup.

Solution 7 - C++

If you use gcc, you can use the warning -Wc++-compat to give you warnings about C code which is dubious in C++ in some way. Its currently used in gcc itself, and its gotten a lot better recently (maybe try a nightly version to get the best you can).

(This doesn't strictly answer the question, but folk might like it).

Solution 8 - C++

#include <stdio.h>

int new (int n) {
    return n/2;
}

int main(void) {
    printf("%d\n", new(10));
    return 0;
}

See also the C++ FAQ entry.

Solution 9 - C++

The single biggest difference I think is that this is a valid C source file:

int main()
{
    foo();
}

Note that I haven't declared foo anywhere.

Aside from language differences, C++ also makes some changes to the library that it inherited from C, e.g. some functions return const char * instead of char *.

Solution 10 - C++

A number of the answers here cover syntax differences that would cause C++ compilers to fail on C89 (or C99) source code. However, there are some subtle language differences that are legal in both languages but that would produce different behavior. The sizeof (char) difference that Naveen mentioned is one example, but https://stackoverflow.com/questions/2038200/write-a-program-that-will-print-c-if-compiled-as-an-ansi-c-program-and-c/ lists some others.

Solution 11 - C++

C compilers generally allowed a little corner cutting that C++ doesn't. C++ is much more strict than C. And generally, some of these differences are compiler-dependant. g++ allows some things that the Intel C++ compiler doesn't, for instance. Even fairly well written C code won't compile with a modern C++ compiler.

Solution 12 - C++

You cannot compare languages only by syntax. If you do that maybe you can see C as a subset of C++. In my opinion the fact that C++ is OO (and C isn't) is enough to say that C and C++ are different languages.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionn00ki3View Question on Stackoverflow
Solution 1 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 2 - C++NaveenView Answer on Stackoverflow
Solution 3 - C++Graeme PerrowView Answer on Stackoverflow
Solution 4 - C++mmxView Answer on Stackoverflow
Solution 5 - C++Pavel MinaevView Answer on Stackoverflow
Solution 6 - C++David ThornleyView Answer on Stackoverflow
Solution 7 - C++Paul BiggarView Answer on Stackoverflow
Solution 8 - C++Sinan ÜnürView Answer on Stackoverflow
Solution 9 - C++Daniel EarwickerView Answer on Stackoverflow
Solution 10 - C++jamesdlinView Answer on Stackoverflow
Solution 11 - C++xcrampsView Answer on Stackoverflow
Solution 12 - C++fnurglewitzView Answer on Stackoverflow