views:

805

answers:

16

I read in a lot of books the claim that "C is a subset of C++".
Actually some (good?) books say: "C is a subset of C++ except the little Details".

I am interested what these details are. I've never seen one.

+8  A: 

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++.

Mehrdad Afshari
any explanation . why not ?
n00ki3
C++ should require an explicit cast to `int*`.
Mehrdad Afshari
Long answer: malloc returns `void *`, which in C can be assigned to any pointer type, and C++ cannot be assigned to any other pointer type.
Daniel Earwicker
It's worth noting that some consider this poor style in C also since some C compilers require the explicit cast.
Imagist
Imagist: a C compiler, as defined by ANSI C89 standard, shouldn't complain.
Mehrdad Afshari
It's legal C. The cast is unnecessary, possible to get wrong, and covers up a failure to include <stdlib.h>. I consider Mehrdad's statement to be the right way to write it in C.
David Thornley
@Imagist: I usually hear the opposite from C programmers. They consider it poor style to add the cast, as it may conceal bugs. Good C code does *not* use the cast.
jalf
@jalf: I consider using implicit function declarations to be poor style, and I strongly encourage always compiling with -Wall -Werror (GCC). This prevents the case where a cast here would mask a failure to include <stdlib.h>. If there's any chance whatsoever the code might get compiled as C++, it's better to do the cast.
Adam Rosenfield
@Adam: If there's any chance that the code might get compiled as C++, it's arguably better to remove the cast. Most C++ compilers will compile C as well, and I'd rather know if a compiler is compiling C as if it were C++.
David Thornley
Prior to C89, malloc() and calloc() returned char*, so an explicit cast was necessary if the target pointer was of a different type. But if you're working with a compiler *that* old, you have bigger problems AFAIC.
John Bode
@jalf: Hang out on comp.lang.c and you'll see religious debates about it on a fairly regular basis. Apparently, this is as big a deal as using EMACS over Vim.
greyfade
+13  A: 

Wikipedia has a good summary of the differences: Compatibility of C and C++

Robert Gamble
Discussion verbiage not withstanding, the information appears to be accurate and fairly complete. I didn't see anything that was wrong and the only thing I can think of off the top of my head that I didn't see there was the difference between "int func();" and "int func(void);" which mean two different things in C but are the same in C++.
Robert Gamble
@Martin: so fix it. That's what Wikipedia is for.
Beska
@Beska: If only I had the time to do stackoverflow and Wikiupdates.
Martin York
+12  A: 

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

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

Naveen
This is my favorite C ism.
Martin York
That can be simpified to: In C, `'a'` is an `int`. In C++, `'a'` is a `char`.
pmg
+3  A: 
#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.

Sinan Ünür
+7  A: 

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;
Graeme Perrow
it's true, but that's exactly what subset means.
yeyeyerman
@yeyeyerman: No. For it to be a subset, all C code would have to be valid C++ as well. The code in this example is valid C but not C++.
jalf
No, if C was a strict subset of C++, then every C program would be a valid C++ program, but that's not true. The question is why it's not true, and this is one example of why.
Graeme Perrow
Ha! Didn't think about this one!
Gab Royer
+1  A: 

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 *.

Daniel Earwicker
Right, prototypes are not required in C but it is usually considered bad practice to not use them.
Robert Gamble
Indeed, I think C99 finally deprecated this. Even so, it is still allowed and used in old codebases.
Daniel Earwicker
You should do `s,C,C89,` and note that it is an invalid C99 source file.
Johannes Schaub - litb
Is it invalid or just deprecated in C99 though?
jalf
@jalf the C99 draft documents the changes to C89, and includes both "remove implicit int" and "remove implicit function declaration".
Johannes Schaub - litb
A: 

One of the original design goals of C++ was to be a superset of C so every valid C program will be a valid C++ program (the only reason C++ is based on the C syntax is to provide an easy migration path from the then most popular programing language).

but that was a long time ago and both the C and C++ standards have advanced a long way and in different directions - so it's no longer true

Nir
Not true. C++ was never a strict superset C - as soon as they introduced new keywords (see my answer to this question), they couldn't guarantee that every C program would compile with a C++ compiler.
Graeme Perrow
I've always been frustrated by this. While the backward-compatibility certainly helped adoption, it is also a near-crippling flaw: many syntax constructs that make sense in C don't make sense in C++. I'm glad that D made the decision to drop backwards-compatibility with C++ early.
Imagist
@Imagist - as did Java. What does that have to do with this?!
Daniel Earwicker
Getting off-topic, Java didn't drop enough C syntax. Keeping the C switch statement was a Bad Idea, and IIRC it kept to the old awkward C operator precedence.
David Thornley
I'd say Java is more on-topic than D! We're talking about languages people actually use...
Daniel Earwicker
Interesting, I always thought the same thing... Learn something new every day....
Frank V
+7  A: 

A full detailed list, with citations to the various C and C++ standards, can be found here: Incompatibilities between ISO C and ISO C++.

Adam Rosenfield
+5  A: 

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.

Pavel Minaev
Your last example is invalid C: The three tags (`struct`, `union` and `enum`) share the same namespace. A better example would be `struct foo { ... }; typedef enum { ... } foo;`
schot
@schot: you're of course right, thank you for the correction. Updated.
Pavel Minaev
A: 

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.

xcramps
+38  A: 
Johannes Schaub - litb
+1. as always, concise, clear, complete.
Mehrdad Afshari
@mehrdad, thanks. oO didn't know one has to create a variable already when declaring a nested struct in C. Fixed.
Johannes Schaub - litb
+2  A: 

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).

C allows implicit int in many contexts, and C++ doesn't. This means that all functions must be declared in C++, while in C 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.

David Thornley
Let's not forget the fact that, in C, you must declare variables at the beginning of a scope (i.e., immediately after an opening brace), whereas, C++ allows variable declarations anywhere.
RobH
However, that's something C++ can do that C can't. I think we're looking at things you can do in C but not C++.
David Thornley
@RobH: That's true for C89 but not for C99.
jamesdlin
A: 

Standard C++ contains all information with samples.

Kirill V. Lyadvinsky
A: 

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.

tr3
paercebal
A: 

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).

Paul Biggar
A: 

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 http://stackoverflow.com/questions/2038200/write-a-program-that-will-print-c-if-compiled-as-an-ansi-c-program-and-c/ lists some others.

jamesdlin