122 lines
5.9 KiB
Markdown
122 lines
5.9 KiB
Markdown
[basic.indet]
|
||
|
||
# 6 Basics [[basic]](./#basic)
|
||
|
||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.indet)
|
||
|
||
### 6.8.5 Indeterminate and erroneous values [basic.indet]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4119)
|
||
|
||
When storage for an object with automatic or dynamic storage duration
|
||
is obtained,
|
||
the bytes comprising the storage for the object
|
||
have the following initial value:
|
||
|
||
- [(1.1)](#1.1)
|
||
|
||
If the object has dynamic storage duration, or
|
||
is the object associated with a variable or function parameter
|
||
whose first declaration is marked with
|
||
the [[indeterminate]] attribute ([[dcl.attr.indet]](dcl.attr.indet "9.13.6 Indeterminate storage")),
|
||
the bytes have [*indeterminate values*](#def:value,indeterminate "6.8.5 Indeterminate and erroneous values [basic.indet]");
|
||
|
||
- [(1.2)](#1.2)
|
||
|
||
otherwise, the bytes have [*erroneous values*](#def:value,erroneous "6.8.5 Indeterminate and erroneous values [basic.indet]"),
|
||
where each value is determined by the implementation
|
||
independently of the state of the program[.](#1.sentence-1)
|
||
|
||
If no initialization is performed for an object (including subobjects),
|
||
such a byte retains its initial value
|
||
until that value is replaced ([[dcl.init.general]](dcl.init.general "9.5.1 General"), [[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#1.sentence-2)
|
||
|
||
If any bit in the value representation has an indeterminate value,
|
||
the object has an indeterminate value;
|
||
otherwise, if any bit in the value representation has an erroneous value,
|
||
the object has an erroneous value ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion"))[.](#1.sentence-3)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Objects with static or thread storage duration are zero-initialized,
|
||
see [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization")[.](#1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4148)
|
||
|
||
Except in the following cases,
|
||
if an indeterminate value is produced by an evaluation,
|
||
the behavior is undefined, and
|
||
if an erroneous value is produced by an evaluation,
|
||
the behavior is erroneous and
|
||
the result of the evaluation is the value so produced but is not erroneous:
|
||
|
||
- [(2.1)](#2.1)
|
||
|
||
If an indeterminate or erroneous value of
|
||
unsigned ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))
|
||
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"))
|
||
is produced by the evaluation of:
|
||
* [(2.1.1)](#2.1.1)
|
||
|
||
the second or third operand of a [conditional expression](expr.cond "7.6.16 Conditional operator [expr.cond]"),
|
||
|
||
* [(2.1.2)](#2.1.2)
|
||
|
||
the right operand of a [comma expression](expr.comma "7.6.20 Comma operator [expr.comma]"),
|
||
|
||
* [(2.1.3)](#2.1.3)
|
||
|
||
the operand of a cast or conversion ([[conv.integral]](conv.integral "7.3.9 Integral conversions"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))
|
||
to an unsigned ordinary character type
|
||
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis")), or
|
||
|
||
* [(2.1.4)](#2.1.4)
|
||
|
||
a [discarded-value expression](expr.context#def:discarded-value_expression "7.2.3 Context dependence [expr.context]"),
|
||
|
||
then the result of the operation is an indeterminate value or
|
||
that erroneous value, respectively[.](#2.1.sentence-1)
|
||
|
||
- [(2.2)](#2.2)
|
||
|
||
If an indeterminate or erroneous value of
|
||
unsigned ordinary character type or std::byte type
|
||
is produced by the evaluation of
|
||
the right operand of a simple assignment operator ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))
|
||
whose first operand is an lvalue of
|
||
unsigned ordinary character type or std::byte type,
|
||
an indeterminate value or that erroneous value, respectively, replaces
|
||
the value of the object referred to by the left operand[.](#2.2.sentence-1)
|
||
|
||
- [(2.3)](#2.3)
|
||
|
||
If an indeterminate or erroneous value of unsigned ordinary character type
|
||
is produced by the evaluation of the initialization expression
|
||
when initializing an object of unsigned ordinary character type,
|
||
that object is initialized to an indeterminate
|
||
value or that erroneous value, respectively[.](#2.3.sentence-1)
|
||
|
||
- [(2.4)](#2.4)
|
||
|
||
If an indeterminate value of
|
||
unsigned ordinary character type or std::byte type
|
||
is produced by the evaluation of the initialization expression
|
||
when initializing an object of std::byte type,
|
||
that object is initialized to an indeterminate value or
|
||
that erroneous value, respectively[.](#2.4.sentence-1)
|
||
|
||
Converting an indeterminate or erroneous value of
|
||
unsigned ordinary character type or std::byte type
|
||
produces an indeterminate or erroneous value, respectively[.](#2.sentence-2)
|
||
|
||
In the latter case,
|
||
the result of the conversion is the value of the converted operand[.](#2.sentence-3)
|
||
|
||
[*Example [1](#example-1)*: int f(bool b) {unsigned char *c = new unsigned char; unsigned char d = *c; // OK, d has an indeterminate valueint e = d; // undefined behaviorreturn b ? d : 0; // undefined behavior if b is true}int g(bool b) {unsigned char c; unsigned char d = c; // no erroneous behavior, but d has an erroneous value assert(c == d); // holds, both integral promotions have erroneous behaviorint e = d; // erroneous behaviorreturn b ? d : 0; // erroneous behavior if b is true}void h() {int d1, d2; int e1 = d1; // erroneous behaviorint e2 = d1; // erroneous behavior assert(e1 == e2); // holds assert(e1 == d1); // holds, erroneous behavior assert(e2 == d1); // holds, erroneous behavior std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but d2 has an erroneous value assert(e1 == d2); // holds, erroneous behavior assert(e2 == d2); // holds, erroneous behavior} â *end example*]
|