There are many claims that any use of uninitialised variables invokes undefined behavior (UB).
Perusing the docs, I could not verify that claim, so I would like a convincing argument clarifying this for both C and C++.
I expect the same semantics for both, but am prepared to be surprised by subtle or not so subtle differences.
Some examples of using uninitialised variables to get started. Please add others as needed to explain any corner-cases they don't cover.
void test1() {
int x;
printf("%d", x);
}
void test2() {
int x;
for(int i = 0; i < CHAR_BIT * sizeof x)
x = x << 1;
printf("%d", x);
}
void test3() {
unsigned x;
printf("%u", x); /* was format "%d" */
}
void test4() {
unsigned x;
for(int i = 0; i < CHAR_BIT * sizeof x)
x = x << 1;
printf("%u", x); /* was format "%d" */
}
C
C11 6.7.9/10
Indeterminate values are handled as follows:
C11 6.2.6.1/5
There's a comment to the above normative text:
(emphasis mine)
Furthermore, left-shifting a signed int variable containing an indeterminate value can also lead to undefined behavior in case it is interpreted as a negative one:
C11 6.5.7/4
All four cases invoke undefined behavior in C since the uninitialized automatic variable never has its address taken. See different answer.
By the way,
sizeof(x)
is defined since the expression is not actually evaluated: it's a compile time evaluation that decays to the type.In the latest C++1y draft(N3936) this is clearly undefined behavior since the language on indeterminate values and undefined behavior has been clarified and it now says in section
8.5
:and goes on to list exception for some unsigned narrow character types only.
Previously in C++ we had to rely on the underspecified lvalue-to-rvalue conversion to prove undefined behavior, which is problematic in the general case. In this case we do have an lalue-to-rvalue conversion. If we look at section
5.2.2
Function call paragraph 7 which says (emphasis mine):In C all of them are undefined behavior, but for a reason that probably not comes directly to mind. Accessing an object with indeterminate value has undefined behavior if it is "memoryless" that is 6.3.2.1 p2
Otherwise, if the address is taken, the interpretation of what indeterminate means concretely in this case is not unanimous. There are people that expect such a value to be fixed once it is first read, others speak of something like "woobly" (or so) values that can be different at each access.
In summary, don't do it. (But that you probably knew already.)
(And not talking about the error using "%d" for an
unsigned
.)With respect to C, the behavior of all the examples
ismay be undefined:Chapter and verse
In all four cases,
x
has automatic storage duration and is not explicitly initialized, meaning its value is indeterminate; if this indeterminate value is a trap representation, then the behavior is undefined.EDIT
Removed reference to appendix J, as it is non-normative.