C in C++. Is it C or C++? [duplicate] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
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++?

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

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

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;

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

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.

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.

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

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

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

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 Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ program lists some others.

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.

Related

Can we design C as a subset of C++ language (even though if it violates C standard bodies) [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
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++?
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);
In C, sizeof('a') is equal to sizeof(int).
In C++, sizeof('a') is equal to sizeof(char).
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;
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++.
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.
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.
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).
#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.
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 *.
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 Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ program lists some others.
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.

Why is return type before the function name?

The new C++11 standard adds a new function declaration syntax with a trailing return type:
// Usual declaration
int foo();
// New declaration
auto foo() -> int;
This syntax has the advantage of letting the return type be deduced, as in:
template<class T, class U>
auto bar(T t, U u) -> decltype(t + u);
But then why the return type was put before the function name in the first place? I imagine that one answer will be that there was no need for such type deduction in that time. If so, is there a reason for a hypothetical new programming language to not use trailing return type by default?
As always, K&R are the "bad guys" here. They devised that function syntax for C, and C++ basically inherited it as-is.
Wild guessing here:
In C, the declaration should hint at the usage, i.e., how to get the value out of something. This is reflected in:
simple values: int i;, int is accessed by writing i
pointers: int *p;, int is accessed by writing *p
arrays: int a[n];, int is accessed by writing a[n]
functions: int f();, int is accessed by writing f()
So, the whole choice depended on the "simple values" case. And as #JerryCoffin already noted, the reason we got type name instead of name : type is probably buried in the ancient history of programming languages. I guess K&R took type name as it's easier to put the emphasis on usage and still have pointers etc. be types.
If they had chosen name : type, they would've either disjoined usage from declarations: p : int* or would've made pointers not be types anymore and instead be something like a decoration to the name: *p : int.
On a personal note: Imagine if they had chosen the latter and C++ inherited that - it simply wouldn't have worked, since C++ puts the emphasis on types instead of usage. This is also the reason why int* p is said to be the "C++ way" and int *p to be the "C way".
If so, is there a reason for a hypothetical new programming language to not use trailing return type by default?
Is there a reason to not use deduction by default? ;) See, e.g. Python or Haskell (or any functional language for that matter, IIRC) - no return types explicitly specified. There's also a movement to add this feature to C++, so sometime in the future you might see just auto f(auto x){ return x + 42; } or even []f(x){ return x + 42; }.
C++ is based on C, which was based on B, which was based on BCPL which was based on CPL.
I suspect that if you were to trace the whole history, you'd probably end up at Fortran, which used declarations like integer x (as opposed to, for example, Pascal, which used declarations like: var x : integer;).
Likewise, for a function, Pascal used something like function f(<args>) : integer; Under the circumstances, it's probably safe to guess that (at least in this specific respect) Pascal's syntax probably would have fit a bit better with type deduction.

Why is the C++ variable declaration syntax inconsistent?

when I declare C++ variables, I do it like this:
int a,b,c,d;
or
string strA,strB,strC,strD;
I.e., first the type then a comma separated list of variable names.
However, I declare pointers like this:
int *a,*b,*c,*d;
and references like this:
int &a,&b,&c,&d;
To be consistent it should be
int* a,b,c,d;
and
int& a,b,c,d;
Why is it not consistent?
The best answer I've seen as to why things like * apply to variables and not to types is the idea that declaration should follow use.
Basically, how you declare a variable should look similar to how you use a variable.
For example,
int *a, b;
...
*a = 42;
b = 314159;
...the use of a and b looks similar to the declaration of a and b.
There's even a citation for this behavior from Dennis Ritchie, one of the creators of C:
Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear...In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.
Dennis Ritchie, The Development of the C Language. History of Programming Languages-II ed. Thomas J. Bergin, Jr. and Richard G. Gibson, Jr. ACM Press (New York) and Addison-Wesley (Reading, Mass), 1996; ISBN 0-201-89502-1.
It's because of the C heritage. The * modifier applies to the variable in C. So the C++ designers made & to apply to the variable as well by analogy, since they couldn't change the first without breaking C compatibility. Same is true for the array syntax too:
int anInt, *aPointerToInt, anArrayOfInt[100];
In The Design and Evolution of C++ Bjarne Stroustrup says he wasn't happy with this but had to accept it for C compatibility. He was unhappy with this in particular:
int *a[10];
It's not clear from the declaration if a is a pointer to an array or an array of pointers (it's an array of pointers, you need brackets to override).
Of course, you can always use a typedef to clean things up a little.
The reason is: in reality & and * in C and C++ applies to variable and no to type.
So the problem is that if you want to declare 4 pointer to integers you should write
int *a, *b, *c, *d;
Writing int* a, b; means
int *a;
int b;
For this reason a lot of people prefer to write int *a; than int* a;, just code style.
Of course int* is a type, but the C syntax states clearly that in a variable declaration * and & will apply to variable.
This happens for the same reason that arrays in C are declared in this way:
int a[10], b;
std::cout << typeid(a).name() << std::endl; // it will print int[10]
std::cout << typeid(b).name() << std::endl; // it will print int
In other languages like C# instead the syntax int[] array; is used.
Another thing is the pointer to function syntax:
// Now we declare a variable that is a pointer to function
int (*pt2Function)(char, char) = NULL;
We are applying the * to the variable name.
It seems to me that the use of * and & applied to the variable, also if 90% of us would prefer differently, is more consistent with the rest of the language.
In the same way, going back to arrays:
// Now we declare a variable that is a pointer to an array of 10 integers.
int (*arrayptr)[10];
C has a rule for its declarations: Declarations mimic use. What this means is that the declaration for a variable looks like the way the variable is used. For example:
int i;
Using this variable looks like i, and that expression results in an int.
int *i;
Using this variable looks like *i, and that expression results in an int. This also implies that an expression i results in a pointer to an int.
int i(void);
Using this variable looks like i(), and results in an int. This also implies i is a function that takes nothing and that returns an int.
int (*i[5])();
Using this variable looks like (*i[x])(), and results in an int. This also implies *i[x] is a function returning int, and i[x] is a pointer to a function returning int, and i is an array of pointers to functions returning int.
So:
int a, *b, c(void), (*d[5])(void);
declares several expressions which all have the type int, but the variables themselves are not all ints.
N.B. in declarations of function and arrays the sub declarations don't literally resemble the use of the variable. I.e. int i[5]; doesn't mean that you need to put a '5' inside the square brackets when you use i, and int i(int); doesn't mean you call the function by saying i(int);. Also declarations of variables of struct types don't match their use since you'd have to declare expressions for each member variable.
Related to the syntax for declaring variables is that of typedefs. To declare a typedef with a certain type, you use the same syntax as for declaring a variable of the desired type, but you stick typedef in front of the declaration and the variable name becomes the typedef name.
typedef int (*array_of_function_pointers[5])(void);
C++ adds references, templates, pointers to member, and a bunch of stuff. It tries to some extent to follow the old C convention, but that convention doesn't really work all that well for many of the things C++ adds, so you do start getting inconsistencies. You'll just have to learn the idiosyncrasies and chalk it up to an imperfect marriage between C and C++.
C++ has inherited this syntax from C. The K&R book (§5.1) says that the expression
int *ip, **ipp;
is intended to be mnemonic (i.e. you read “*ip and **ipp have type int”), they wanted it to mimic usage syntax.
I agree it is quite cryptic and counterintuitive for humans, and inconsistent with typedefs, e.g.
typedef int* intptr;
intptr a, b; // equivalent to: int *a, *b
but it never really was C++ author's decision, the choice to make the language compatible with C implied using this syntax, that's why.

Is there const in C?

This question may be naive, but:
is there const keyword in C?
since which version?
are there any semantic and/or syntactic differences between const in C and C++?
There are no syntactic differences between C and C++ with regard to const keyword, besides a rather obscure one: in C (since C99) you can declare function parameters as
void foo(int a[const]);
which is equivalent to
void foo(int *const a);
declaration. C++ does not support such syntax.
Semantic differences exist as well. As #Ben Voigt already noted, in C const declarations do not produce constant expressions, i.e. in C you can't use a const int object in a case label, as a bit-field width or as array size in a non-VLA array declaration (all this is possible in C++). Also, const objects have external linkage by default in C (internal linkage in C++).
There's at least one more semantic difference, which Ben did not mention. Const-correctness rules of C++ language support the following standard conversion
int **pp = 0;
const int *const *cpp = pp; // OK in C++
int ***ppp = 0;
int *const *const *cppp = ppp; // OK in C++
These initializations are illegal in C.
int **pp = 0;
const int *const *cpp = pp; /* ERROR in C */
int ***ppp = 0;
int *const *const *cppp = ppp; /* ERROR in C */
Generally, when dealing with multi-level pointers, C++ says that you can add const-qualification at any depth of indirection, as long as you also add const-qualification all the way to the top level.
In C you can only add const-qualification to the type pointed by the top-level pointer, but no deeper.
int **pp = 0;
int *const *cpp = pp; /* OK in C */
int ***ppp = 0;
int **const *cppp = ppp; /* OK in C */
Another manifestation of the same underlying general principle is the way const-correctness rules work with arrays in C and C++. In C++ you can do
int a[10];
const int (*p)[10] = &a; // OK in C++
Trying to do the same in C will result in an error
int a[10];
const int (*p)[10] = &a; /* ERROR in C */
The first two questions are answered here: Const in C
Yes there are quite a few differences in semantics between const in C and C++.
In C++, const variables of appropriate type are integral constant expressions (if their initializers are compile-time constant expressions) and can be used in context which requires that, such as array bounds, and in enum definitions. In C, they are not and cannot be.
In C++, const global variables automatically have static linkage, so you can put them in header files. In C, such variables have external linkage and that would generate duplicate definition errors at link time.
Yes, there is a const keyword. It was added as part of the 1989 standard.
As far as compatibility, here's a paragraph from Harbison & Steele, 5th edition:
A top-level declaration that has the type qualifier const but no explicit storage class is considered to be static in C++ but extern in C. To remain compatible, examine top-level const declarations and provide an explicit storage class.
In C++, string constants are implicitly const; they are not in C.
Yes, const has been there since at least since ANSI C (aka C89).
It certainly appears in my copy of "The C Programming Language (2nd Edition)", Kernighan & Ritchie (published in 1988).
Relevant extract:
The const and volatile properties are new with the ANSI standard. The purpose of const is to
announce objects that may be placed in read-only memory, and perhaps to increase opportunities for
optimization.
Two other differences:
const arraytype (i.e typedef int A[1]; const A a = { 0 };) specifies a constant array type ( http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#112 and http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1059 ) (and whose elements are so-qualified too) in C++, but a non-constant array type whose elements are so-qualified in C.
const const is valid in C99 (not valid in C89), not valid in C++ in any version (you can only semantically repeat a const, not syntactically). It contracts to const in C99.
Yes. const is there in C, from C89.
Here is a good read is about behaviour of const keyword in C.
The semantic in C is different than in C++. For example,
unsigned const a = 10;
unsigned A[a];
in file scope would be valid in C++, but not in C.
Yes, there's a const keyword in C. It's been there since C90.
Syntactically, it can occur in the same places as in C++. Semantically, it's a bit more lax, IIRC.
According to ESR, const was added in the ANSI C Draft Proposed Standard. Eric Giguere's summary of ANSI C, dated 1987, confirms it.
This looks like the draft itself -- search for "3.5.3 Type qualifiers".
There is a "const" keyword in C, and it has been for a long time. If a variable is designated "const", writes to it are forbidden.
Additionally, in some environments, variables declared "const" may be located in a different data segment from other variables. This data segment may offer hardware write protection, and for embedded systems, may be stored in ROM or flash memory rather than in RAM (a very important distinction on some processors which have a lot more ROM or flash than RAM--e.g. 128 KB flash and 3.5 KB RAM, or 2 KB ROM and 96 bytes RAM).
Note that the compiler will generally not make any inferences about "const" values or expressions involving them. If I say "const char foo[] = "Hello";" and then later make reference to foo[1], the compiler will load the value (which will most likely be 'e') from wherever foo[] is stored and use the loaded value. Sometimes this usefully allows values to be patched in a compiled code image, but sometimes it just wastes code.
If you want to define a number to to be a compile-time "substitutable" constant, the best way, at least for integer constants, may be to use "enum". For example, "enum {woozle=19;}" will cause 19 to be substituted for "woozle" throughout the code. Note that unlike textual substitutions; enum declarations obey proper rules of scope.

Where is C not a subset of C++? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
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++?
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);
In C, sizeof('a') is equal to sizeof(int).
In C++, sizeof('a') is equal to sizeof(char).
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;
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++.
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.
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.
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).
#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.
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 *.
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 Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ program lists some others.
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.