1465 lines
43 KiB
Markdown
1465 lines
43 KiB
Markdown
[diff.iso]
|
||
|
||
# Annex C (informative) Compatibility [[diff]](./#diff)
|
||
|
||
## C.7 C++ and C [diff.iso]
|
||
|
||
### [C.7.1](#general) General [[diff.iso.general]](diff.iso.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2738)
|
||
|
||
Subclause [diff.iso] lists the differences between C++ and C,
|
||
in addition to those listed above,
|
||
by the chapters of this document[.](#general-1.sentence-1)
|
||
|
||
### [C.7.2](#diff.lex) [[lex]](lex "5 Lexical conventions"): lexical conventions [[diff.lex]](diff.lex)
|
||
|
||
[1](#diff.lex-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2746)
|
||
|
||
**Affected subclause:** [[lex.key]](lex.key)
|
||
|
||
|
||
**Change:** New Keywords[.](#diff.lex-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
New keywords are added to C++;
|
||
see [[lex.key]](lex.key "5.12 Keywords")[.](#diff.lex-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** These keywords were added in order to implement the new
|
||
semantics of C++[.](#diff.lex-1.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.lex-1.sentence-4)
|
||
|
||
Any C programs that used any of these keywords as identifiers
|
||
are not valid C++ programs[.](#diff.lex-1.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.lex-1.sentence-6)
|
||
|
||
Converting one specific program is easy[.](#diff.lex-1.sentence-7)
|
||
|
||
Converting a large collection
|
||
of related programs takes more work[.](#diff.lex-1.sentence-8)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common[.](#diff.lex-1.sentence-9)
|
||
|
||
[2](#diff.lex-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2766)
|
||
|
||
**Affected subclause:** [[lex.ccon]](lex.ccon)
|
||
|
||
|
||
**Change:** Type of [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]") is changed from int to char[.](#diff.lex-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** This is needed for improved overloaded function argument type
|
||
matching[.](#diff.lex-2.sentence-2)
|
||
|
||
[*Example [1](#diff.lex-example-1)*: int function( int i );int function( char c );
|
||
|
||
function( 'x' );
|
||
|
||
It is preferable that this call match the second version of
|
||
function rather than the first[.](#diff.lex-2.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.lex-2.sentence-4)
|
||
|
||
C programs which depend onsizeof('x') == sizeof(int) will not work the same as C++ programs[.](#diff.lex-2.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Simple[.](#diff.lex-2.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Programs which depend upon sizeof('x') are probably rare[.](#diff.lex-2.sentence-7)
|
||
|
||
[3](#diff.lex-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2794)
|
||
|
||
**Affected subclause:** [[lex.string]](lex.string)
|
||
|
||
|
||
**Change:** Concatenated [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* can no longer have
|
||
conflicting [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3 Character literals [lex.ccon]")es[.](#diff.lex-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Removal of non-portable feature[.](#diff.lex-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Concatenation of [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* with different [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3 Character literals [lex.ccon]")es
|
||
is now ill-formed[.](#diff.lex-3.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.lex-3.sentence-4)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.lex-3.sentence-5)
|
||
|
||
[4](#diff.lex-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2809)
|
||
|
||
**Affected subclause:** [[lex.string]](lex.string)
|
||
|
||
|
||
**Change:** String literals made const[.](#diff.lex-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
The type of a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") is changed
|
||
from âarray of charâ
|
||
to âarray of const charâ[.](#diff.lex-4.sentence-2)
|
||
|
||
The type of a UTF-8 string literal is changed
|
||
from âarray of charâ
|
||
to âarray of const char8_tâ[.](#diff.lex-4.sentence-3)
|
||
|
||
The type of a UTF-16 string literal is changed
|
||
from âarray of *some-integer-type*â
|
||
to âarray of const char16_tâ[.](#diff.lex-4.sentence-4)
|
||
|
||
The type of a UTF-32 string literal is changed
|
||
from âarray of *some-integer-type*â
|
||
to âarray of const char32_tâ[.](#diff.lex-4.sentence-5)
|
||
|
||
The type of a wide string literal is changed
|
||
from âarray of wchar_tâ
|
||
to âarray of const wchar_tâ[.](#diff.lex-4.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Rationale:** This avoids calling an inappropriate overloaded function,
|
||
which might expect to be able to modify its argument[.](#diff.lex-4.sentence-7)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.lex-4.sentence-8)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.lex-4.sentence-9)
|
||
|
||
The fix is to add a cast:char* p = "abc"; // valid in C, invalid in C++void f(char*) {char* p = (char*)"abc"; // OK, cast added f(p);
|
||
f((char*)"def"); // OK, cast added}
|
||
|
||
**How widely used:** Programs that have a legitimate reason to treat string literal objects
|
||
as potentially modifiable memory are probably rare[.](#diff.lex-4.sentence-11)
|
||
|
||
### [C.7.3](#diff.basic) [[basic]](basic "6 Basics"): basics [[diff.basic]](diff.basic)
|
||
|
||
[1](#diff.basic-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2851)
|
||
|
||
**Affected subclause:** [[basic.def]](basic.def)
|
||
|
||
|
||
**Change:** C++ does not have âtentative definitionsâ as in C.
|
||
|
||
[*Example [1](#diff.basic-example-1)*:
|
||
|
||
At file scope,int i;int i; is valid in C, invalid in C++[.](#diff.basic-1.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
This makes it impossible to define
|
||
mutually referential file-local objects with static storage duration,
|
||
if initializers are restricted to the syntactic forms of C[.](#diff.basic-1.sentence-2)
|
||
|
||
[*Example [2](#diff.basic-example-2)*: struct X { int i; struct X* next; };
|
||
|
||
static struct X a;static struct X b = { 0, &a };static struct X a = { 1, &b }; â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** This avoids having different initialization rules for
|
||
fundamental types and user-defined types[.](#diff.basic-1.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.basic-1.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.basic-1.sentence-5)
|
||
|
||
In C++, the initializer for one of a set of
|
||
mutually-referential file-local objects with static storage
|
||
duration must invoke a function
|
||
call to achieve the initialization[.](#diff.basic-1.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.basic-1.sentence-7)
|
||
|
||
[2](#diff.basic-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2888)
|
||
|
||
**Affected subclause:** [[basic.scope]](basic.scope)
|
||
|
||
|
||
**Change:** A struct is a scope in C++, not in C.
|
||
|
||
[*Example [3](#diff.basic-example-3)*:
|
||
|
||
struct X {struct Y { int a; } b;};struct Y c; is valid in C but not in C++, which would require X::Y c;[.](#diff.basic-2.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
**Rationale:** Class scope is crucial to C++, and a struct is a class[.](#diff.basic-2.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.basic-2.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.basic-2.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** C programs use struct extremely frequently, but the
|
||
change is only noticeable when struct, enumeration, or enumerator
|
||
names are referred to outside the struct[.](#diff.basic-2.sentence-6)
|
||
|
||
The latter is probably rare[.](#diff.basic-2.sentence-7)
|
||
|
||
[3](#diff.basic-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2912)
|
||
|
||
**Affected subclause:** [[basic.link]](basic.link) [also [[dcl.type]](dcl.type "9.2.9 Type specifiers")]
|
||
|
||
**Change:** A name of file scope that is explicitly declared const, and not explicitly
|
||
declared extern, has internal linkage, while in C it would have external linkage[.](#diff.basic-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Because const objects may be used as values during translation in
|
||
C++, this feature urges programmers to provide an explicit initializer
|
||
for each const object[.](#diff.basic-3.sentence-3)
|
||
|
||
This feature allows the user to put const objects in source files that are included
|
||
in more than one translation unit[.](#diff.basic-3.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.basic-3.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.basic-3.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.basic-3.sentence-7)
|
||
|
||
[4](#diff.basic-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2929)
|
||
|
||
**Affected subclause:** [[basic.start.main]](basic.start.main)
|
||
|
||
|
||
**Change:** The main function cannot be called recursively and cannot have its address taken[.](#diff.basic-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The main function may require special actions[.](#diff.basic-4.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.basic-4.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Trivial: create an intermediary function such asmymain(argc, argv)[.](#diff.basic-4.sentence-4)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.basic-4.sentence-5)
|
||
|
||
[5](#diff.basic-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2942)
|
||
|
||
**Affected subclause:** [[basic.types]](basic.types)
|
||
|
||
|
||
**Change:** C allows âcompatible typesâ in several places, C++ does not[.](#diff.basic-5.sentence-1)
|
||
|
||
|
||
|
||
|
||
For example,
|
||
otherwise-identical struct types with different tag names
|
||
are âcompatibleâ in C but are distinctly different types
|
||
in C++[.](#diff.basic-5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Stricter type checking is essential for C++[.](#diff.basic-5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.basic-5.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.basic-5.sentence-5)
|
||
|
||
The âtypesafe linkageâ mechanism will find many, but not all,
|
||
of such problems[.](#diff.basic-5.sentence-6)
|
||
|
||
Those problems not found by typesafe linkage will continue to
|
||
function properly,
|
||
according to the âlayout compatibility rulesâ of this
|
||
document[.](#diff.basic-5.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common[.](#diff.basic-5.sentence-8)
|
||
|
||
### [C.7.4](#diff.expr) [[expr]](expr "7 Expressions"): expressions [[diff.expr]](diff.expr)
|
||
|
||
[1](#diff.expr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L2966)
|
||
|
||
**Affected subclause:** [[conv.ptr]](conv.ptr)
|
||
|
||
|
||
**Change:** Converting void* to a pointer-to-object type requires casting[.](#diff.expr-1.sentence-1)
|
||
|
||
[*Example [1](#diff.expr-example-1)*: char a[10];void* b=a;void foo() {char* c=b;}
|
||
|
||
C accepts this usage of pointer to void being assigned
|
||
to a pointer to object type[.](#diff.expr-1.sentence-2)
|
||
|
||
C++ does not[.](#diff.expr-1.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ tries harder than C to enforce compile-time type safety[.](#diff.expr-1.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.expr-1.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Can be automated[.](#diff.expr-1.sentence-6)
|
||
|
||
Violations will be diagnosed by the C++ translator[.](#diff.expr-1.sentence-7)
|
||
|
||
The fix is to add a cast[.](#diff.expr-1.sentence-8)
|
||
|
||
[*Example [2](#diff.expr-example-2)*: char* c = (char*) b; â *end example*]
|
||
|
||
|
||
|
||
|
||
**How widely used:** This is fairly widely used but it is good
|
||
programming practice to add the cast when assigning pointer-to-void to pointer-to-object[.](#diff.expr-1.sentence-9)
|
||
|
||
Some C translators will give a warning
|
||
if the cast is not used[.](#diff.expr-1.sentence-10)
|
||
|
||
[2](#diff.expr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3002)
|
||
|
||
**Affected subclause:** [[expr.arith.conv]](expr.arith.conv)
|
||
|
||
|
||
**Change:** Operations mixing a value of an enumeration type and a value of a different
|
||
enumeration type or of a floating-point type are not valid[.](#diff.expr-2.sentence-1)
|
||
|
||
[*Example [3](#diff.expr-example-3)*: enum E1 { e };enum E2 { f };int b = e <= 3.7; // valid in C; ill-formed in C++int k = f - e; // valid in C; ill-formed in C++int x = 1 ? e : f; // valid in C; ill-formed in C++ â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** Reinforcing type safety in C++[.](#diff.expr-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Well-formed C code will not compile with this International Standard[.](#diff.expr-2.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Violations will be diagnosed by the C++ translator[.](#diff.expr-2.sentence-4)
|
||
|
||
The original behavior can be restored with a cast or integral promotion[.](#diff.expr-2.sentence-5)
|
||
|
||
[*Example [4](#diff.expr-example-4)*: enum E1 { e };enum E2 { f };int b = (int)e <= 3.7;int k = +f - e; â *end example*]
|
||
|
||
|
||
|
||
|
||
**How widely used:** Uncommon[.](#diff.expr-2.sentence-6)
|
||
|
||
[3](#diff.expr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3033)
|
||
|
||
**Affected subclauses:** [[expr.post.incr]](expr.post.incr) and [[expr.pre.incr]](expr.pre.incr)
|
||
|
||
|
||
**Change:** Decrement operator is not allowed with bool operand[.](#diff.expr-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Feature with surprising semantics[.](#diff.expr-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C expression utilizing the decrement operator on
|
||
a bool lvalue
|
||
(for instance, via the C typedef in [<stdbool.h>](stdbool.h.syn#header:%3cstdbool.h%3e "17.15.5 Header <stdbool.h> synopsis [stdbool.h.syn]"))
|
||
is ill-formed in C++[.](#diff.expr-3.sentence-3)
|
||
|
||
[4](#diff.expr-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3044)
|
||
|
||
**Affected subclauses:** [[expr.sizeof]](expr.sizeof) and [[expr.cast]](expr.cast)
|
||
|
||
|
||
**Change:** In C++, types can only be defined in declarations, not in expressions[.](#diff.expr-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
In C, a sizeof expression or cast expression may define a new type[.](#diff.expr-4.sentence-2)
|
||
|
||
[*Example [5](#diff.expr-example-5)*:
|
||
|
||
p = (void*)(struct x {int i;} *)0; defines a new type, struct x[.](#diff.expr-4.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** This prohibition helps to clarify the location of
|
||
definitions in the source code[.](#diff.expr-4.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.expr-4.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.expr-4.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.expr-4.sentence-7)
|
||
|
||
[5](#diff.expr-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3064)
|
||
|
||
**Affected subclauses:** [[expr.rel]](expr.rel) and [[expr.eq]](expr.eq)
|
||
|
||
|
||
**Change:** C allows directly comparing two objects of array type; C++ does not[.](#diff.expr-5.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The behavior is confusing because it compares not the contents of the two
|
||
arrays, but their addresses[.](#diff.expr-5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature that had unspecified behavior
|
||
in common use cases[.](#diff.expr-5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Violations will be diagnosed by the C++ translator[.](#diff.expr-5.sentence-4)
|
||
|
||
The original behavior
|
||
can be replicated by explicitly casting either array to a pointer, such as by
|
||
using a unary +[.](#diff.expr-5.sentence-5)
|
||
|
||
[*Example [6](#diff.expr-example-6)*: int arr1[5];int arr2[5];int same = arr1 == arr2; // valid C, ill-formed C++int idem = arr1 == +arr2; // valid in both C and C++ â *end example*]
|
||
|
||
|
||
|
||
|
||
**How widely used:** Rare[.](#diff.expr-5.sentence-6)
|
||
|
||
[6](#diff.expr-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3088)
|
||
|
||
**Affected subclauses:** [[expr.cond]](expr.cond), [[expr.assign]](expr.assign), and [[expr.comma]](expr.comma)
|
||
|
||
|
||
**Change:** The result of a conditional expression, an assignment expression, or a comma expression may be an lvalue[.](#diff.expr-6.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ is an object-oriented language, placing relatively
|
||
more emphasis on lvalues[.](#diff.expr-6.sentence-2)
|
||
|
||
For example, function calls may
|
||
yield lvalues[.](#diff.expr-6.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.expr-6.sentence-4)
|
||
|
||
Some C
|
||
expressions that implicitly rely on lvalue-to-rvalue
|
||
conversions will yield different results[.](#diff.expr-6.sentence-5)
|
||
|
||
[*Example [7](#diff.expr-example-7)*:
|
||
|
||
char arr[100];sizeof(0, arr) yields100 in C++ andsizeof(char*) in C[.](#diff.expr-6.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Programs must add explicit casts to the appropriate rvalue[.](#diff.expr-6.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Rare[.](#diff.expr-6.sentence-8)
|
||
|
||
### [C.7.5](#diff.stat) [[stmt]](stmt "8 Statements"): statements [[diff.stat]](diff.stat)
|
||
|
||
[1](#diff.stat-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3120)
|
||
|
||
**Affected subclauses:** [[stmt.switch]](stmt.switch) and [[stmt.goto]](stmt.goto)
|
||
|
||
|
||
**Change:** It is now invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered)[.](#diff.stat-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Constructors used in initializers may allocate
|
||
resources which need to be de-allocated upon leaving the
|
||
block[.](#diff.stat-1.sentence-2)
|
||
|
||
Allowing jump past initializers would require
|
||
complicated runtime determination of allocation[.](#diff.stat-1.sentence-3)
|
||
|
||
Furthermore, many operations on such an uninitialized object
|
||
have undefined behavior[.](#diff.stat-1.sentence-4)
|
||
|
||
With this simple compile-time rule, C++ assures that
|
||
if an initialized variable is in scope, then it has assuredly been
|
||
initialized[.](#diff.stat-1.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.stat-1.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.stat-1.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.stat-1.sentence-8)
|
||
|
||
[2](#diff.stat-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3141)
|
||
|
||
**Affected subclause:** [[stmt.return]](stmt.return)
|
||
|
||
|
||
**Change:** It is now invalid to return (explicitly or implicitly) from a function which is
|
||
declared to return a value without actually returning a value[.](#diff.stat-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The caller and callee may assume fairly elaborate
|
||
return-value mechanisms for the return of class objects[.](#diff.stat-2.sentence-2)
|
||
|
||
If
|
||
some flow paths execute a return without specifying any value,
|
||
the implementation must embody many more complications[.](#diff.stat-2.sentence-3)
|
||
|
||
Besides,
|
||
promising to return a value of a given type, and then not returning
|
||
such a value, has always been recognized to be a questionable
|
||
practice, tolerated only because very-old C had no distinction between
|
||
functions with void and int return types[.](#diff.stat-2.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.stat-2.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.stat-2.sentence-6)
|
||
|
||
Add an appropriate return value to the source code, such as zero[.](#diff.stat-2.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.stat-2.sentence-8)
|
||
|
||
For several years, many existing C implementations have produced warnings in
|
||
this case[.](#diff.stat-2.sentence-9)
|
||
|
||
### [C.7.6](#diff.dcl) [[dcl]](dcl "9 Declarations"): declarations [[diff.dcl]](diff.dcl)
|
||
|
||
[1](#diff.dcl-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[.](#diff.dcl-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
Using these specifiers with type declarations is illegal in C++[.](#diff.dcl-1.sentence-2)
|
||
|
||
In C, these specifiers are ignored when used on type declarations[.](#diff.dcl-1.sentence-3)
|
||
|
||
[*Example [1](#diff.dcl-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[.](#diff.dcl-1.sentence-4)
|
||
|
||
In C++, class members can be declared with the static storage
|
||
class specifier[.](#diff.dcl-1.sentence-5)
|
||
|
||
Storage class specifiers on type
|
||
declarations can be confusing for users[.](#diff.dcl-1.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-1.sentence-7)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-1.sentence-8)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-1.sentence-9)
|
||
|
||
[2](#diff.dcl-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[.](#diff.dcl-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The storage class specifier had no effect in C++[.](#diff.dcl-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-2.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-2.sentence-4)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common[.](#diff.dcl-2.sentence-5)
|
||
|
||
[3](#diff.dcl-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)[.](#diff.dcl-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)[.](#diff.dcl-3.sentence-2)
|
||
|
||
[*Example [2](#diff.dcl-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[.](#diff.dcl-3.sentence-3)
|
||
|
||
[*Example [3](#diff.dcl-example-3)*: class name { /* ... */ };
|
||
name i; // i has type class name â *end example*]
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-3.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.dcl-3.sentence-5)
|
||
|
||
One of the 2 types has to be renamed[.](#diff.dcl-3.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-3.sentence-7)
|
||
|
||
[4](#diff.dcl-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[.](#diff.dcl-4.sentence-2)
|
||
|
||
**Rationale:** A const object cannot be assigned to so it must be initialized
|
||
to hold a useful value[.](#diff.dcl-4.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-4.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.dcl-4.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-4.sentence-6)
|
||
|
||
[5](#diff.dcl-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[.](#diff.dcl-5.sentence-1)
|
||
|
||
[*Example [4](#diff.dcl-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[.](#diff.dcl-5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-5.sentence-4)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Rare[.](#diff.dcl-5.sentence-5)
|
||
|
||
[6](#diff.dcl-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[.](#diff.dcl-6.sentence-1)
|
||
|
||
In C, an empty parameter list means that the number and type of the function arguments are unknown[.](#diff.dcl-6.sentence-2)
|
||
|
||
[*Example [5](#diff.dcl-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[.](#diff.dcl-6.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.dcl-6.sentence-4)
|
||
|
||
This feature was marked as âobsolescentâ in C[.](#diff.dcl-6.sentence-5)
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-6.sentence-6)
|
||
|
||
The function declarations using C incomplete declaration style must
|
||
be completed to become full prototype declarations[.](#diff.dcl-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[.](#diff.dcl-6.sentence-8)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common[.](#diff.dcl-6.sentence-9)
|
||
|
||
[7](#diff.dcl-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[.](#diff.dcl-7.sentence-2)
|
||
|
||
In C, these type definitions are allowed[.](#diff.dcl-7.sentence-3)
|
||
|
||
[*Example [6](#diff.dcl-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[.](#diff.dcl-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[.](#diff.dcl-7.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-7.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.dcl-7.sentence-7)
|
||
|
||
The type definitions must be moved to file scope, or in header files[.](#diff.dcl-7.sentence-8)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-7.sentence-9)
|
||
|
||
This style of type definition is seen as poor coding style[.](#diff.dcl-7.sentence-10)
|
||
|
||
[8](#diff.dcl-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[.](#diff.dcl-8.sentence-1)
|
||
|
||
In C, âold-styleâ syntax is allowed, but deprecated as âobsolescentâ[.](#diff.dcl-8.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Prototypes are essential to type safety[.](#diff.dcl-8.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-8.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-8.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common in old programs, but already known to be obsolescent[.](#diff.dcl-8.sentence-6)
|
||
|
||
[9](#diff.dcl-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[.](#diff.dcl-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[.](#diff.dcl-9.sentence-2)
|
||
|
||
[*Example [7](#diff.dcl-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[.](#diff.dcl-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[.](#diff.dcl-9.sentence-4)
|
||
|
||
Nested designators are seldom used[.](#diff.dcl-9.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of feature that is incompatible with C++[.](#diff.dcl-9.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-9.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Out-of-order initializers are common[.](#diff.dcl-9.sentence-8)
|
||
|
||
The other features are seldom used[.](#diff.dcl-9.sentence-9)
|
||
|
||
[10](#diff.dcl-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[.](#diff.dcl-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'[.](#diff.dcl-10.sentence-2)
|
||
|
||
[*Example [8](#diff.dcl-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[.](#diff.dcl-10.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-10.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.dcl-10.sentence-5)
|
||
|
||
The arrays must be declared one element bigger to contain the
|
||
string terminating '\0'[.](#diff.dcl-10.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-10.sentence-7)
|
||
|
||
This style of array initialization is seen as poor coding style[.](#diff.dcl-10.sentence-8)
|
||
|
||
[11](#diff.dcl-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[.](#diff.dcl-11.sentence-1)
|
||
|
||
In C, objects of enumeration type can be assigned values of any integral type[.](#diff.dcl-11.sentence-2)
|
||
|
||
[*Example [9](#diff.dcl-example-9)*: enum color { red, blue, green };enum color c = 1; // valid C, invalid C++ â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** The type-safe nature of C++[.](#diff.dcl-11.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-11.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-11.sentence-5)
|
||
|
||
(The type error produced by the assignment can be automatically
|
||
corrected by applying an explicit cast[.](#diff.dcl-11.sentence-6))
|
||
|
||
|
||
|
||
|
||
**How widely used:** Common[.](#diff.dcl-11.sentence-7)
|
||
|
||
[12](#diff.dcl-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[.](#diff.dcl-12.sentence-1)
|
||
|
||
In C, the type of an enumerator is int[.](#diff.dcl-12.sentence-2)
|
||
|
||
[*Example [10](#diff.dcl-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[.](#diff.dcl-12.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.dcl-12.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.dcl-12.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-12.sentence-6)
|
||
|
||
The only time this affects existing C code is when the size of an
|
||
enumerator is taken[.](#diff.dcl-12.sentence-7)
|
||
|
||
Taking the size of an enumerator is not a
|
||
common C coding practice[.](#diff.dcl-12.sentence-8)
|
||
|
||
[13](#diff.dcl-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]")[.](#diff.dcl-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*[.](#diff.dcl-13.sentence-2)
|
||
|
||
[*Example [11](#diff.dcl-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]")[.](#diff.dcl-13.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.dcl-13.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.dcl-13.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.dcl-13.sentence-6)
|
||
|
||
### [C.7.7](#diff.class) [[class]](class "11 Classes"): classes [[diff.class]](diff.class)
|
||
|
||
[1](#diff.class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3483)
|
||
|
||
**Affected subclause:** [[class.name]](class.name) [see also [[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")]
|
||
|
||
**Change:** In C++, a class declaration introduces the class name into the scope where it is
|
||
declared and hides any object, function or other declaration of that name in an enclosing
|
||
scope[.](#diff.class-1.sentence-2)
|
||
|
||
In C, an inner scope declaration of a struct tag name never hides the name of an
|
||
object or function in an outer scope[.](#diff.class-1.sentence-3)
|
||
|
||
[*Example [1](#diff.class-example-1)*: int x[99];void f() {struct x { int a; }; sizeof(x); /* size of the array in C *//* size of the struct in *C++* */} â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** This is one of the few incompatibilities between C and C++ that
|
||
can be attributed to the new C++ name space definition where a
|
||
name can be declared as a type and as a non-type in a single scope
|
||
causing the non-type name to hide the type name and requiring that
|
||
the keywords class, struct, union or enum be used to refer to the type name[.](#diff.class-1.sentence-4)
|
||
|
||
This new name space definition provides important notational
|
||
conveniences to C++ programmers and helps making the use of the
|
||
user-defined types as similar as possible to the use of fundamental
|
||
types[.](#diff.class-1.sentence-5)
|
||
|
||
The advantages of the new name space definition were judged to
|
||
outweigh by far the incompatibility with C described above[.](#diff.class-1.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.class-1.sentence-7)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.class-1.sentence-8)
|
||
|
||
If the hidden name that needs to be accessed is at global scope,
|
||
the :: C++ operator can be used[.](#diff.class-1.sentence-9)
|
||
|
||
If the hidden name is at block scope, either the type or the struct
|
||
tag has to be renamed[.](#diff.class-1.sentence-10)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.class-1.sentence-11)
|
||
|
||
[2](#diff.class-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3523)
|
||
|
||
**Affected subclause:** [[class.copy.ctor]](class.copy.ctor)
|
||
|
||
|
||
**Change:** Copying volatile objects[.](#diff.class-2.sentence-1)
|
||
|
||
The implicitly-declared copy constructor and
|
||
implicitly-declared copy assignment operator
|
||
cannot make a copy of a volatile lvalue[.](#diff.class-2.sentence-2)
|
||
|
||
[*Example [2](#diff.class-example-2)*:
|
||
|
||
The following is valid in C:struct X { int i; };volatile struct X x1 = {0};struct X x2 = x1; // invalid C++struct X x3;
|
||
x3 = x1; // also invalid C++
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** Several alternatives were debated at length[.](#diff.class-2.sentence-4)
|
||
|
||
Changing the parameter tovolatileconstX& would greatly complicate the generation of
|
||
efficient code for class objects[.](#diff.class-2.sentence-5)
|
||
|
||
Discussion of
|
||
providing two alternative signatures for these
|
||
implicitly-defined operations raised
|
||
unanswered concerns about creating
|
||
ambiguities and complicating
|
||
the rules that specify the formation of
|
||
these operators according to the bases and
|
||
members[.](#diff.class-2.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.class-2.sentence-7)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.class-2.sentence-8)
|
||
|
||
If volatile semantics are required for the copy,
|
||
a user-declared constructor or assignment must
|
||
be provided[.](#diff.class-2.sentence-9)
|
||
|
||
If non-volatile semantics are required,
|
||
an explicitconst_cast can be used[.](#diff.class-2.sentence-10)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.class-2.sentence-11)
|
||
|
||
[3](#diff.class-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3571)
|
||
|
||
**Affected subclause:** [[class.bit]](class.bit)
|
||
|
||
|
||
**Change:** Bit-fields of type plain int are signed[.](#diff.class-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The signedness needs to be consistent among template specializations[.](#diff.class-3.sentence-2)
|
||
|
||
For consistency,
|
||
the implementation freedom was eliminated for non-dependent types,
|
||
too[.](#diff.class-3.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** The choice is implementation-defined in C, but not so in C++[.](#diff.class-3.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#diff.class-3.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.class-3.sentence-6)
|
||
|
||
[4](#diff.class-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3587)
|
||
|
||
**Affected subclause:** [[class.nest]](class.nest)
|
||
|
||
|
||
**Change:** In C++, the name of a nested class is local to its enclosing class[.](#diff.class-4.sentence-1)
|
||
|
||
In C
|
||
the name of the nested class belongs to the same scope as the name of the outermost enclosing class[.](#diff.class-4.sentence-2)
|
||
|
||
[*Example [3](#diff.class-example-3)*: struct X {struct Y { /* ... */ } y;};struct Y yy; // valid C, invalid C++ â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ classes have member functions which require that classes
|
||
establish scopes[.](#diff.class-4.sentence-3)
|
||
|
||
The C rule would leave classes as an incomplete scope mechanism
|
||
which would prevent C++ programmers from maintaining locality
|
||
within a class[.](#diff.class-4.sentence-4)
|
||
|
||
A coherent set of scope rules for C++ based on the C rule would
|
||
be very complicated and C++ programmers would be unable to predict
|
||
reliably the meanings of nontrivial examples involving nested or
|
||
local functions[.](#diff.class-4.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.class-4.sentence-6)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.class-4.sentence-7)
|
||
|
||
To make the struct type name visible in the scope of the enclosing
|
||
struct, the struct tag can be declared in the scope of the
|
||
enclosing struct, before the enclosing struct is defined[.](#diff.class-4.sentence-8)
|
||
|
||
[*Example [4](#diff.class-example-4)*: struct Y; // struct Y and struct X are at the same scopestruct X {struct Y { /* ... */ } y;}; â *end example*]
|
||
|
||
All the definitions of C struct types enclosed in other struct
|
||
definitions and accessed outside the scope of the enclosing
|
||
struct can be exported to the scope of the enclosing struct[.](#diff.class-4.sentence-9)
|
||
|
||
Note: this is a consequence of the difference in scope rules,
|
||
which is documented in [[basic.scope]](basic.scope "6.4 Scope")[.](#diff.class-4.sentence-10)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.class-4.sentence-11)
|
||
|
||
[5](#diff.class-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3634)
|
||
|
||
**Affected subclause:** [[class.member.lookup]](class.member.lookup)
|
||
|
||
|
||
**Change:** In C++, a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") may not be redeclared in a class definition after being used in that definition[.](#diff.class-5.sentence-1)
|
||
|
||
[*Example [5](#diff.class-example-5)*: typedef int I;struct S { I i; int I; // valid C, invalid C++}; â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** When classes become complicated, allowing such a redefinition
|
||
after the type has been used can create confusion for C++
|
||
programmers as to what the meaning of I really is[.](#diff.class-5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#diff.class-5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.class-5.sentence-4)
|
||
|
||
Either the type or the struct member has to be renamed[.](#diff.class-5.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#diff.class-5.sentence-6)
|
||
|
||
### [C.7.8](#diff.cpp) [[cpp]](cpp "15 Preprocessing directives"): preprocessing directives [[diff.cpp]](diff.cpp)
|
||
|
||
[1](#diff.cpp-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3661)
|
||
|
||
**Affected subclause:** [[cpp.predefined]](cpp.predefined)
|
||
|
||
|
||
**Change:** Whether __STDC__ is defined and if so, what its value is, areimplementation-defined[.](#diff.cpp-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ is not identical to C[.](#diff.cpp-1.sentence-2)
|
||
|
||
Mandating that __STDC__ be defined would require that translators make an incorrect claim[.](#diff.cpp-1.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#diff.cpp-1.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Semantic transformation[.](#diff.cpp-1.sentence-5)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Programs and headers that reference __STDC__ are
|
||
quite common[.](#diff.cpp-1.sentence-6)
|