Files
2025-10-25 03:02:53 +03:00

495 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[diff.dcl]
# Annex C (informative) Compatibility [[diff]](./#diff)
## C.7 C++ and C [[diff.iso]](diff.iso#diff.dcl)
### C.7.6 [[dcl]](dcl "9Declarations"): 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.4The 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.4The 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.7Program 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.5Sizeof")]
**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.1General[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.1Attribute syntax and semantics[dcl.attr.grammar]") is an [*attribute-specifier*](dcl.attr.grammar#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#13.sentence-1)
In C, an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute 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.1Attribute 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)