Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consequences of uninitialised variables: int vs unsigned char

I saw the following example on cppreference.com

int x;     // OK: the value of x is indeterminate int y = x; // undefined behavior 

Here, int y = x; is undefined behavior because x is uninitialized.

But,

unsigned char c;     // OK: the value of c is indeterminate unsigned char d = c; // OK: the value of d is indeterminate 

Here, unsigned char d = c; is indeterminate behavior, but unsigned char c; is also an uninitialized variable.

So, Why is the value of unsigned char d indeterminate?

like image 787
msc Avatar asked Aug 04 '17 12:08

msc


People also ask

Why are uninitialized variables bad?

"Uninitialized variables contain some value" is a incorrect statement which unfortunately is teached. A program who access an uninitialized variable has Undefined Behavior, which means it can have any behavior.

What is the value of uninitialized value?

INTRODUCTION: An uninitialized variable has an undefined value, often corresponding to the data that was already in the particular memory location that the variable is using.

Can you use uninitialized variables in C #?

Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location!


2 Answers

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

    • [...]

    • the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4)

    • [...]

    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 
like image 197
bolov Avatar answered Oct 01 '22 05:10

bolov


From the page you referenced: assigning from an indeterminate value is undefined behavior except

If the indeterminate value of unsigned narrow character type or std::byte is assigned to another variable with unsigned narrow character type or std::byte (the value of the variable becomes indeterminate, but the behavior is not undefined)

I believe this is because default initialization may place any combination of bits into the variable and while the standard guarantees that an unsigned narrow character type may take on values represented by every possible bit pattern, there is no such guarantee for other types.

like image 21
joshwilsonvu Avatar answered Oct 01 '22 04:10

joshwilsonvu