[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 <stdalign.h>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)
