[diff.dcl] # Annex C (informative) Compatibility [[diff]](./#diff) ## C.7 C++ and C [[diff.iso]](diff.iso#diff.dcl) ### C.7.6 [[dcl]](dcl "9 Declarations"): declarations [diff.dcl] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3168) **Affected subclause:** [[dcl.stc]](dcl.stc) **Change:** In C++, the static or extern specifiers can only be applied to names of objects or functions[.](#1.sentence-1) Using these specifiers with type declarations is illegal in C++[.](#1.sentence-2) In C, these specifiers are ignored when used on type declarations[.](#1.sentence-3) [*Example [1](#example-1)*: static struct S { // valid C, invalid in C++int i;}; — *end example*] **Rationale:** Storage class specifiers don't have any meaning when associated with a type[.](#1.sentence-4) In C++, class members can be declared with the static storage class specifier[.](#1.sentence-5) Storage class specifiers on type declarations can be confusing for users[.](#1.sentence-6) **Effect on original feature:** Deletion of semantically well-defined feature[.](#1.sentence-7) **Difficulty of converting:** Syntactic transformation[.](#1.sentence-8) **How widely used:** Seldom[.](#1.sentence-9) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3196) **Affected subclause:** [[dcl.stc]](dcl.stc) **Change:** In C++, register is not a storage class specifier[.](#2.sentence-1) **Rationale:** The storage class specifier had no effect in C++[.](#2.sentence-2) **Effect on original feature:** Deletion of semantically well-defined feature[.](#2.sentence-3) **Difficulty of converting:** Syntactic transformation[.](#2.sentence-4) **How widely used:** Common[.](#2.sentence-5) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3208) **Affected subclause:** [[dcl.typedef]](dcl.typedef) **Change:** A C++ [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") 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)[.](#3.sentence-1) In C, a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") and a struct tag name declared in the same scope can have the same name (because they have different name spaces)[.](#3.sentence-2) [*Example [2](#example-2)*: typedef struct name1 { /* ... */ } name1; // valid C and C++struct name { /* ... */ };typedef int name; // valid C, invalid C++ — *end example*] **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[.](#3.sentence-3) [*Example [3](#example-3)*: class name { /* ... */ }; name i; // i has type class name — *end example*] **Effect on original feature:** Deletion of semantically well-defined feature[.](#3.sentence-4) **Difficulty of converting:** Semantic transformation[.](#3.sentence-5) One of the 2 types has to be renamed[.](#3.sentence-6) **How widely used:** Seldom[.](#3.sentence-7) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3243) **Affected subclause:** [[dcl.type]](dcl.type) [see also [[basic.link]](basic.link "6.7 Program and linkage")] **Change:** Const objects must be initialized in C++ but can be left uninitialized in C[.](#4.sentence-2) **Rationale:** A const object cannot be assigned to so it must be initialized to hold a useful value[.](#4.sentence-3) **Effect on original feature:** Deletion of semantically well-defined feature[.](#4.sentence-4) **Difficulty of converting:** Semantic transformation[.](#4.sentence-5) **How widely used:** Seldom[.](#4.sentence-6) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3256) **Affected subclause:** [[dcl.spec.auto]](dcl.spec.auto) **Change:** The keyword auto cannot be used as a storage class specifier[.](#5.sentence-1) [*Example [4](#example-4)*: void f() {auto int x; // valid C, invalid C++} — *end example*] **Rationale:** Allowing the use of auto to deduce the type of a variable from its initializer results in undesired interpretations ofauto as a storage class specifier in certain contexts[.](#5.sentence-2) **Effect on original feature:** Deletion of semantically well-defined feature[.](#5.sentence-3) **Difficulty of converting:** Syntactic transformation[.](#5.sentence-4) **How widely used:** Rare[.](#5.sentence-5) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3279) **Affected subclause:** [[dcl.fct]](dcl.fct) **Change:** In C++, a function declared with an empty parameter list takes no arguments[.](#6.sentence-1) In C, an empty parameter list means that the number and type of the function arguments are unknown[.](#6.sentence-2) [*Example [5](#example-5)*: int f(); // means int f(void) in C++// int f( unknown ) in C — *end example*] **Rationale:** This is to avoid function calls with the wrong number or type of arguments[.](#6.sentence-3) **Effect on original feature:** Change to semantics of well-defined feature[.](#6.sentence-4) This feature was marked as “obsolescent” in C[.](#6.sentence-5) **Difficulty of converting:** Syntactic transformation[.](#6.sentence-6) The function declarations using C incomplete declaration style must be completed to become full prototype declarations[.](#6.sentence-7) A program may need to be updated further if different calls to the same (non-prototype) function have different numbers of arguments or if the type of corresponding arguments differed[.](#6.sentence-8) **How widely used:** Common[.](#6.sentence-9) [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3307) **Affected subclause:** [[dcl.fct]](dcl.fct) [see [[expr.sizeof]](expr.sizeof "7.6.2.5 Sizeof")] **Change:** In C++, types may not be defined in return or parameter types[.](#7.sentence-2) In C, these type definitions are allowed[.](#7.sentence-3) [*Example [6](#example-6)*: void f( struct S { int a; } arg ) {} // valid C, invalid C++enum E { A, B, C } f() {} // valid C, invalid C++ — *end example*] **Rationale:** When comparing types in different translation units, C++ relies on name equivalence when C relies on structural equivalence[.](#7.sentence-4) Regarding parameter types: since the type defined in a parameter list would be in the scope of the function, the only legal calls in C++ would be from within the function itself[.](#7.sentence-5) **Effect on original feature:** Deletion of semantically well-defined feature[.](#7.sentence-6) **Difficulty of converting:** Semantic transformation[.](#7.sentence-7) The type definitions must be moved to file scope, or in header files[.](#7.sentence-8) **How widely used:** Seldom[.](#7.sentence-9) This style of type definition is seen as poor coding style[.](#7.sentence-10) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3334) **Affected subclause:** [[dcl.fct.def]](dcl.fct.def) **Change:** In C++, the syntax for function definition excludes the “old-style” C function[.](#8.sentence-1) In C, “old-style” syntax is allowed, but deprecated as “obsolescent”[.](#8.sentence-2) **Rationale:** Prototypes are essential to type safety[.](#8.sentence-3) **Effect on original feature:** Deletion of semantically well-defined feature[.](#8.sentence-4) **Difficulty of converting:** Syntactic transformation[.](#8.sentence-5) **How widely used:** Common in old programs, but already known to be obsolescent[.](#8.sentence-6) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3347) **Affected subclause:** [[dcl.init.aggr]](dcl.init.aggr) **Change:** In C++, designated initialization support is restricted compared to the corresponding functionality in C[.](#9.sentence-1) In C++, designators for non-static data members must be specified in declaration order, designators for array elements and nested designators are not supported, and designated and non-designated initializers cannot be mixed in the same initializer list[.](#9.sentence-2) [*Example [7](#example-7)*: struct A { int x, y; };struct B { struct A a; };struct A a = {.y = 1, .x = 2}; // valid C, invalid C++int arr[3] = {[1] = 5}; // valid C, invalid C++struct B b = {.a.x = 0}; // valid C, invalid C++struct A c = {.x = 1, 2}; // valid C, invalid C++ — *end example*] **Rationale:** In C++, members are destroyed in reverse construction order and the elements of an initializer list are evaluated in lexical order, so member initializers must be specified in order[.](#9.sentence-3) Array designators conflict with [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") syntax[.](#9.sentence-4) Nested designators are seldom used[.](#9.sentence-5) **Effect on original feature:** Deletion of feature that is incompatible with C++[.](#9.sentence-6) **Difficulty of converting:** Syntactic transformation[.](#9.sentence-7) **How widely used:** Out-of-order initializers are common[.](#9.sentence-8) The other features are seldom used[.](#9.sentence-9) [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3384) **Affected subclause:** [[dcl.init.string]](dcl.init.string) **Change:** In C++, when initializing an array of character with a string, the number of characters in the string (including the terminating '\0') must not exceed the number of elements in the array[.](#10.sentence-1) In C, an array can be initialized with a string even if the array is not large enough to contain the string-terminating '\0'[.](#10.sentence-2) [*Example [8](#example-8)*: char array[4] = "abcd"; // valid C, invalid C++ — *end example*] **Rationale:** When these non-terminated arrays are manipulated by standard string functions, there is potential for major catastrophe[.](#10.sentence-3) **Effect on original feature:** Deletion of semantically well-defined feature[.](#10.sentence-4) **Difficulty of converting:** Semantic transformation[.](#10.sentence-5) The arrays must be declared one element bigger to contain the string terminating '\0'[.](#10.sentence-6) **How widely used:** Seldom[.](#10.sentence-7) This style of array initialization is seen as poor coding style[.](#10.sentence-8) [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3409) **Affected subclause:** [[dcl.enum]](dcl.enum) **Change:** C++ objects of enumeration type can only be assigned values of the same enumeration type[.](#11.sentence-1) In C, objects of enumeration type can be assigned values of any integral type[.](#11.sentence-2) [*Example [9](#example-9)*: enum color { red, blue, green };enum color c = 1; // valid C, invalid C++ — *end example*] **Rationale:** The type-safe nature of C++[.](#11.sentence-3) **Effect on original feature:** Deletion of semantically well-defined feature[.](#11.sentence-4) **Difficulty of converting:** Syntactic transformation[.](#11.sentence-5) (The type error produced by the assignment can be automatically corrected by applying an explicit cast[.](#11.sentence-6)) **How widely used:** Common[.](#11.sentence-7) [12](#12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3432) **Affected subclause:** [[dcl.enum]](dcl.enum) **Change:** In C++, the type of an enumerator is its enumeration[.](#12.sentence-1) In C, the type of an enumerator is int[.](#12.sentence-2) [*Example [10](#example-10)*: enum e { A };sizeof(A) == sizeof(int) // in Csizeof(A) == sizeof(e) // in C++/* and sizeof(int) is not necessarily equal to sizeof(e) */ — *end example*] **Rationale:** In C++, an enumeration is a distinct type[.](#12.sentence-3) **Effect on original feature:** Change to semantics of well-defined feature[.](#12.sentence-4) **Difficulty of converting:** Semantic transformation[.](#12.sentence-5) **How widely used:** Seldom[.](#12.sentence-6) The only time this affects existing C code is when the size of an enumerator is taken[.](#12.sentence-7) Taking the size of an enumerator is not a common C coding practice[.](#12.sentence-8) [13](#13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3458) **Affected subclause:** [[dcl.align]](dcl.align) **Change:** In C++, an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is an [*attribute-specifier*](dcl.attr.grammar#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#13.sentence-1) In C, an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is a *declaration-specifier*[.](#13.sentence-2) [*Example [11](#example-11)*: #include unsigned alignas(8) int x; // valid C, invalid C++unsigned int y alignas(8); // valid C++, invalid C — *end example*] **Rationale:** C++ requires unambiguous placement of the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#13.sentence-3) **Effect on original feature:** Deletion of semantically well-defined feature[.](#13.sentence-4) **Difficulty of converting:** Syntactic transformation[.](#13.sentence-5) **How widely used:** Seldom[.](#13.sentence-6)