[dcl.stc]
Change: In C++, the static or extern specifiers can only be applied to names of objects or functions
Using these specifiers with type declarations is illegal in C++.
In C, these specifiers are ignored when used on type declarations.
Example:
static struct S { // valid C, invalid in C++
int i;
};
Rationale:
Storage class specifiers don't have any meaning when associated
with a type.
In C++, class members can be declared with the static storage
class specifier.
Allowing storage class specifiers on type
declarations could render the code confusing for users.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Syntactic transformation.
How widely used:
Seldom.
[dcl.typedef]
Change: A C++ typedef name must be different from any class type name declared
in the same scope (except if the typedef is a synonym of the class name with the
same name). In C, a typedef name and a struct tag name declared in the same scope
can have the same name (because they have different name spaces)
Example:
typedef struct name1 { /*...*/ } name1; // valid C and C++ struct name { /*...*/ }; typedef int name; // valid C, invalid C++
Rationale:
For ease of use, C++ doesn't require that a type name be prefixed
with the keywords class, struct or union when used in object
declarations or type casts.
Example:
class name { /*...*/ }; name i; // i has type class name
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
One of the 2 types has to be renamed.
How widely used:
Seldom.
[dcl.type] [see also [basic.link]]
Change: const objects must be initialized in C++ but can be left uninitialized in C
Rationale:
A const object cannot be assigned to so it must be initialized
to hold a useful value.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
Seldom.
[dcl.type]
Change: Banning implicit int
In C++ a decl-specifier-seq must contain a type-specifier, unless it is followed by a declarator for a constructor, a destructor, or a conversion function. In the following example, the left-hand column presents valid C; the right-hand column presents equivalent C++ :
void f(const parm); void f(const int parm); const n = 3; const int n = 3; main() int main() /* ... */ /* ... */
Rationale:
In C++, implicit int creates several opportunities for
ambiguity between expressions involving function-like
casts and declarations.
Explicit declaration is increasingly considered
to be proper style.
Liaison with WG14 (C) indicated support for (at least)
deprecating implicit int in the next revision of C.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Syntactic transformation.
Could be automated.
How widely used:
Common.
[dcl.spec.auto]
Change:
The keyword auto cannot be used as a storage class specifier.
void f() {
auto int x; // valid C, invalid C++
}
Rationale: Allowing the use of auto to deduce the type
of a variable from its initializer results in undesired interpretations of
auto as a storage class specifier in certain contexts.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Rare.
[dcl.enum]
Change: C++ objects of enumeration type can only be assigned values of the same enumeration type.
In C, objects of enumeration type can be assigned values of any integral type
Example:
enum color { red, blue, green };
enum color c = 1; // valid C, invalid C++
Rationale:
The type-safe nature of C++.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Syntactic transformation.
(The type error produced by the assignment can be automatically
corrected by applying an explicit cast.)
How widely used:
Common.
[dcl.enum]
Change: In C++, the type of an enumerator is its enumeration. In C, the type of an enumerator is int.
Example:
enum e { A }; sizeof(A) == sizeof(int) // in C sizeof(A) == sizeof(e) // in C++ /* and sizeof(int) is not necessarily equal to sizeof(e) */
Rationale:
In C++, an enumeration is a distinct type.
Effect on original feature:
Change to semantics of well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
Seldom.
The only time this affects existing C code is when the size of an
enumerator is taken.
Taking the size of an enumerator is not a
common C coding practice.