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

1465 lines
43 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.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 "5Lexical 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.12Keywords")[.](#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.3Character 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.5String literals[lex.string]")*s* can no longer have
conflicting [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3Character 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.5String literals[lex.string]")*s* with different [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3Character 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.5String 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 "6Basics"): 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.9Type 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 "7Expressions"): 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.5Header <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 "8Statements"): 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 "9Declarations"): 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.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)[.](#diff.dcl-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)[.](#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.7Program 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.5Sizeof")]
**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.1General[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.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]")[.](#diff.dcl-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*[.](#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.1Attribute 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 "11Classes"): 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.4The 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.4Scope")[.](#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.4The 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 "15Preprocessing 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)