235 lines
6.1 KiB
Markdown
235 lines
6.1 KiB
Markdown
[diff.expr]
|
||
|
||
# Annex C (informative) Compatibility [[diff]](./#diff)
|
||
|
||
## C.7 C++ and C [[diff.iso]](diff.iso#diff.expr)
|
||
|
||
### C.7.4 [[expr]](expr "7 Expressions"): expressions [diff.expr]
|
||
|
||
[1](#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[.](#1.sentence-1)
|
||
|
||
[*Example [1](#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[.](#1.sentence-2)
|
||
|
||
C++ does not[.](#1.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ tries harder than C to enforce compile-time type safety[.](#1.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#1.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Can be automated[.](#1.sentence-6)
|
||
|
||
Violations will be diagnosed by the C++ translator[.](#1.sentence-7)
|
||
|
||
The fix is to add a cast[.](#1.sentence-8)
|
||
|
||
[*Example [2](#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[.](#1.sentence-9)
|
||
|
||
Some C translators will give a warning
|
||
if the cast is not used[.](#1.sentence-10)
|
||
|
||
[2](#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[.](#2.sentence-1)
|
||
|
||
[*Example [3](#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++[.](#2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Well-formed C code will not compile with this International Standard[.](#2.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Violations will be diagnosed by the C++ translator[.](#2.sentence-4)
|
||
|
||
The original behavior can be restored with a cast or integral promotion[.](#2.sentence-5)
|
||
|
||
[*Example [4](#example-4)*: enum E1 { e };enum E2 { f };int b = (int)e <= 3.7;int k = +f - e; â *end example*]
|
||
|
||
|
||
|
||
|
||
**How widely used:** Uncommon[.](#2.sentence-6)
|
||
|
||
[3](#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[.](#3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Feature with surprising semantics[.](#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++[.](#3.sentence-3)
|
||
|
||
[4](#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[.](#4.sentence-1)
|
||
|
||
|
||
|
||
|
||
In C, a sizeof expression or cast expression may define a new type[.](#4.sentence-2)
|
||
|
||
[*Example [5](#example-5)*:
|
||
|
||
p = (void*)(struct x {int i;} *)0; defines a new type, struct x[.](#4.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Rationale:** This prohibition helps to clarify the location of
|
||
definitions in the source code[.](#4.sentence-4)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature[.](#4.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Syntactic transformation[.](#4.sentence-6)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Seldom[.](#4.sentence-7)
|
||
|
||
[5](#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[.](#5.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The behavior is confusing because it compares not the contents of the two
|
||
arrays, but their addresses[.](#5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Deletion of semantically well-defined feature that had unspecified behavior
|
||
in common use cases[.](#5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Violations will be diagnosed by the C++ translator[.](#5.sentence-4)
|
||
|
||
The original behavior
|
||
can be replicated by explicitly casting either array to a pointer, such as by
|
||
using a unary +[.](#5.sentence-5)
|
||
|
||
[*Example [6](#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[.](#5.sentence-6)
|
||
|
||
[6](#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[.](#6.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** C++ is an object-oriented language, placing relatively
|
||
more emphasis on lvalues[.](#6.sentence-2)
|
||
|
||
For example, function calls may
|
||
yield lvalues[.](#6.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Change to semantics of well-defined feature[.](#6.sentence-4)
|
||
|
||
Some C
|
||
expressions that implicitly rely on lvalue-to-rvalue
|
||
conversions will yield different results[.](#6.sentence-5)
|
||
|
||
[*Example [7](#example-7)*:
|
||
|
||
char arr[100];sizeof(0, arr) yields100 in C++ andsizeof(char*) in C[.](#6.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
|
||
|
||
|
||
**Difficulty of converting:** Programs must add explicit casts to the appropriate rvalue[.](#6.sentence-7)
|
||
|
||
|
||
|
||
|
||
**How widely used:** Rare[.](#6.sentence-8)
|