Clang won't compile anonymous struct [duplicate] - c++

Some C++ compilers permit anonymous unions and structs as an extension to standard C++. It's a bit of syntactic sugar that's occasionally very helpful.
What's the rationale that prevents this from being part of the standard? Is there a technical roadblock? A philosophical one? Or just not enough of a need to justify it?
Here's a sample of what I'm talking about:
struct vector3 {
union {
struct {
float x;
float y;
float z;
};
float v[3];
};
};
My compiler will accept this, but it warns that "nameless struct/union" is a non-standard extension to C++.

As others have pointed out anonymous unions are permitted in standard C++, but anonymous structs are not.
The reason for this is that C supports anonymous unions but not anonymous structs*, so C++ supports the former for compatibility but not the latter because it's not needed for compatibility.
Furthermore, there's not much use to anonymous structs in C++. The use you demonstrate, to have a struct containing three floats which can be referred to either by .v[i], or .x, .y, and .z, I believe results in undefined behavior in C++. C++ does not allow you to write to one member of a union, say .v[1], and then read from another member, say .y. Although code that does this is not uncommon it is not actually well defined.
C++'s facilities for user-defined types provide alternative solutions. For example:
struct vector3 {
float v[3];
float &operator[] (int i) { return v[i]; }
float &x() { return v[0]; }
float &y() { return v[1]; }
float &z() { return v[2]; }
};
* C11 apparently adds anonymous structs, so a future revision to C++ may add them.

I'll say, you can clean up your vector3 declaration by just using a union
union vector3 {
struct { float x, y, z; } ;
float v[3] ;
} ;
Sure, anonymous structures was an MSVC extension. But ISO C11 permits it now, and gcc allows it, and so does Apple's llvm compiler.
Why in C11 and not C++11? I'm not sure, but practically speaking most (gcc++, MSVC++ and Apple's C++ compiler) C++ compilers support them.

Not sure what you mean. Section 9.5 of the C++ spec, clause 2:
A union of the form
union { member-specification } ;
is called an anonymous union; it defines an unnamed object of unnamed type.
You can do things like this too:
void foo()
{
typedef
struct { // unnamed, is that what you mean by anonymous?
int a;
char b;
} MyStructType; // this is more of a "C" style, but valid C++ nonetheless
struct { // an anonymous struct, not even typedef'd
double x;
double y;
} point = { 1.0, 3.4 };
}
Not always very useful... although sometimes useful in nasty macro definitions.

Unions can be anonymous; see the Standard, 9.5 paragraph 2.
What purpose do you see an anonymous struct or class as fulfilling? Before speculating why something isn't in the Standard, I'd like to have some idea why it should be, and I don't see a use for an anonymous struct.

Based on the edit, the comments, and this MSDN article: Anonymous Structures, I'll hazard a guess - it fits poorly with the concept of encapsulation. I wouldn't expect a member of a class to mess with my class namespace beyond merely adding one member. Furthermore, changes to the anonymous structure can affect my class without permission.

Your code
union {
struct {
float x;
float y;
float z;
};
float v[3];
};
is like
union Foo {
int;
float v[3];
};
which is surely invalid (in C99 and before).
The reason is probably to simplify parsing (in C), because in that case you only need to check that the struct/union body has only "declarator statements" like
Type field;
That said, gcc and "other compilers" supports unnamed fields as an extension.
Edit: Anonymous structs are now officially supported in C11 (ยง6.7.2.1/13).

Edit: I put up a non-answer since I didn't realize the difference between an "anonymous struct" and an "unnamed struct". Rather than delete this answer, I will just leave it up, but my response here is not correct.
Original response follows:
I don't see it mentioned in any of the answers here, I guess since they're mostly written from before the "modern C++" era, but since I found my way here via a google search on "C++ anonymous struct", I'll just put this answer down here:
I'm able to do the following:
struct /* no typename */
{
int i=2;
} g_some_object{};
int main()
{
return g_some_object.i;
}
I noticed this behavior is actually leveraged in some of the examples for C++20 coroutines on cppreference, particularly for demonstrating a task awaiter.
If at any point in the past this behavior was not allowed, then that's no longer the case--we can definitely do this now.

Related

C in C++. Is it C or C++? [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.

Is it legal to use address of one field of a union to access another field?

Consider following code:
union U
{
int a;
float b;
};
int main()
{
U u;
int *p = &u.a;
*(float *)p = 1.0f; // <-- this line
}
We all know that addresses of union fields are usually same, but I'm not sure is it well-defined behavior to do something like this.
So, question is: Is it legal and well-defined behavior to cast and dereference a pointer to union field like in the code above?
P.S. I know that it's more C than C++, but I'm trying to understand if it's legal in C++, not C.
All members of a union must reside at the same address, that is guaranteed by the standard. What you are doing is indeed well-defined behavior, but it shall be noted that you cannot read from an inactive member of a union using the same approach.
Accessing inactive union member - undefined behavior?
Note: Do not use c-style casts, prefer reinterpret_cast in this case.
As long as all you do is write to the other data-member of the union, the behavior is well-defined; but as stated this changes which is considered to be the active member of the union; meaning that you can later only read from that you just wrote to.
union U {
int a;
float b;
};
int main () {
U u;
int *p = &u.a;
reinterpret_cast<float*> (p) = 1.0f; // ok, well-defined
}
Note: There is an exception to the above rule when it comes to layout-compatible types.
The question can be rephrased into the following snippet which is semantically equivalent to a boiled down version of the "problem".
#include <type_traits>
#include <algorithm>
#include <cassert>
int main () {
using union_storage_t = std::aligned_storage<
std::max ( sizeof(int), sizeof(float)),
std::max (alignof(int), alignof(float))
>::type;
union_storage_t u;
int * p1 = reinterpret_cast< int*> (&u);
float * p2 = reinterpret_cast<float*> (p1);
float * p3 = reinterpret_cast<float*> (&u);
assert (p2 == p3); // will never fire
}
What does the Standard (n3797) say?
9.5/1 Unions [class.union]
In a union, at most one of the non-static data members can be
active at any time, that is, the value of at most one of the
non-static dat amembers ca nbe stored in a union at any time.
[...] The size of a union is sufficient to contain the largest of
its non-static data members. Each non-static data member is
allocated as if it were the sole member of a struct. All non-static data members of a union object have the same address.
Note: The wording in C++11 (n3337) was underspecified, even though the intent has always been that of C++14.
Yes, it is legal. Using explicit casts, you can do almost anything.
As other comments have stated, all members in a union start at the same address / location so casting a pointer to a different member is pointless.
The assembly language will be the same. You want to make the code easy to read so I don't recommend the practice. It is confusing and there is no benefit.
Also, I recommend a "type" field so that you know when the data is in float format versus int format.

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.

C++ Undefined behaviour with unions

Was just reading about some anonymous structures and how it is isn't standard and some general use case for it is undefined behaviour...
This is the basic case:
struct Point {
union {
struct {
float x, y;
};
float v[2];
};
};
So writing to x and then reading from v[0] would be undefined in that you would expect them to be the same but it may not be so.
Not sure if this is in the standard but unions of the same type...
union{ float a; float b; };
Is it undefined to write to a and then read from b ?
That is to say does the standard say anything about binary representation of arrays and sequential variables of the same type.
The standard says that reading from any element in a union other
than the last one written is undefined behavior. In theory, the
compiler could generate code which somehow kept track of the
reads and writes, and triggered a signal if you violated the
rule (even if the two are the same type). A compiler could also
use the fact for some sort of optimization: if you write to a
(or x), it can assume that you do not read b (or v[0])
when optimizing.
In practice, every compiler I know supports this, if the union
is clearly visible, and there are cases in many (most?, all?)
where even legal use will fail if the union is not visible
(e.g.:
union U { int i; float f; };
int f( int* pi, int* pf ) { int r = *pi; *pf = 3.14159; return r; }
// ...
U u;
u.i = 1;
std::cout << f( &u.i, &u.f );
I've actually seen this fail with g++, although according to the
standard, it is perfectly legal.)
Also, even if the compiler supports writing to Point::x and
reading from Point::v[0], there's no guarantee that Point::y
and Point::v[1] even have the same physical address.
The standard requires that in a union "[e]ach data member is allocated as if it were the sole member of a struct." (9.5)
It also requires that struct { float x, y; } and float v[2] must have the same internal representation (9.2) and thus you could safely reinterpret cast one as the other
Taken together these two rules guarantee that the union you describe will function provided that it is genuinely written to memory. However, because the standard only requires that the last data member written be valid it's theoretically possible to have an implementation that fails if the union is only used as a local variable. I'd be amazed if that ever actually happens, however.
I did not get why you have used float v[2];
The simple union for a point structure can be defined as:
union{
struct {
float a;
float b;
};
} Point;
You can access the values in unioin as:
Point.a = 10.5;
point.b = 12.2; //example

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.