6 Basics [basic]

6.7 Memory and objects [basic.memobj]

6.7.4 Indeterminate and erroneous values [basic.indet]

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:
  • 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]), the bytes have indeterminate values;
  • otherwise, the bytes have erroneous values, where each value is determined by the implementation independently of the state of the program.
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], [expr.ass]).
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]).
[Note 1: 
Objects with static or thread storage duration are zero-initialized, see [basic.start.static].
— end note]
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:
  • If an indeterminate or erroneous value of unsigned ordinary character type ([basic.fundamental]) or std​::​byte type ([cstddef.syn]) is produced by the evaluation of: then the result of the operation is an indeterminate value or that errorneous value, respectively.
  • 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.ass]) 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.
  • 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.
  • 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.
Converting an indeterminate or erroneous value of unsigned ordinary character type or std​::​byte type produces an indeterminate or erroneous value, respectively.
In the latter case, the result of the conversion is the value of the converted operand.
[Example 1: int f(bool b) { unsigned char *c = new unsigned char; unsigned char d = *c; // OK, d has an indeterminate value int e = d; // undefined behavior return 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 behavior int e = d; // erroneous behavior return b ? d : 0; // erroneous behavior if b is true } void h() { int d1, d2; int e1 = d1; // erroneous behavior int 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]