Online references like cppreference.com are good up to a point. But it is known that sometimes errors or misinterpretations do occasionally slip through. So when dealing with such oddities, it is always a good thing to go to the official C++ standard.
N3936
§8.5 Initializers [dcl.init]
12 [...] When storage for an object with automatic or dynamic storage
duration is obtained, the object has an indeterminate value , and if
no initialization is performed for the object, that object retains an
indeterminate value until that value is replaced (5.17). [...] If an
indeterminate value is produced by an evaluation, the behavior is
undefined except in the following cases:
If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of
then the result of the operation is an indeterminate value.
If an indeterminate value of unsigned narrow character type is produced by the evaluation of the right operand of a simple assignment
operator (5.17) whose first operand is an lvalue of unsigned narrow
character type, an indeterminate value replaces the value of the
object referred to by the left operand
If an indeterminate value of unsigned narrow character type is produced by the evaluation of the initialization expression when
initializing an object of unsigned narrow character type, that object
is initialized to an indeterminate value.
Example:
int f(bool b) {
unsigned char c;
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
}
So (to my big surprise) the standard backs this up.
As for why, the most likely reason can be also found in the standard:
§3.9.1 Fundamental types [basic.fundamental]
1 [...] For unsigned narrow character types, all possible bit patterns
of the value representation represent numbers. These requirements do
not hold for other types
As a side note, I just realized this can be used by an evil interviewer:
Q. Can you in a well-defined behavior change the valid value of an object to an undetermined value? If yes, how?
A.
unsigned char ind;
unsigned char x = 24;
x = ind; // x had a valid value, now x has an indetermined value