Why uninitialized variable print a strange negative value?
What you're doing (reading the value of an uninitialised variable) is undefined behaviour; anything can happen, from it appearing to work, to printing random values, to crashing, to buying pizza with your credit card.
Strange behavior with uninitialized pointers
In general, just don't use uninitialized variables at all. If you want to know more, read on.
All your examples are straight Undefined Behavior (UB), due to this standard passage:
6.3.2.1 Lvalues, arrays, and function designators
[...]
2 [...] If the lvalue designates an object of automatic storage duration that could have been declared with theregister
storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
Now, let's pretend in some omitted line the address was taken.
&i; // Like this
6.2.4 Storage durations of objects
5 An object whose identifier is declared with no linkage and without the storage-class
specifierstatic
has automatic storage duration, as do some compound literals. [...]
6 [...] The initial value of the object is indeterminate.
Alternative quote:
6.7.9 Initialization
[...]
10 If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate.
3.19.2
1 indeterminate value
either an unspecified value or a trap representation3.19.3
1 unspecified value
valid value of the relevant type where this International Standard imposes no
requirements on which value is chosen in any instance
2 NOTE An unspecified value cannot be a trap representation.3.19.4
1 trap representation
an object representation that need not represent a value of the object type
6.2.6.1 General
5 Certain object representations need not represent a value of the object type. If the stored
value of an object has such a representation and is read by an lvalue expression that does
not have character type, the behavior is undefined. If such a representation is produced
by a side effect that modifies all or any part of the object by an lvalue expression that
does not have character type, the behavior is undefined.50) Such a representation is called
a trap representation.
Thus, if your implementation supports trap-representations for the type you read (Yours don't for int*
), you have UB.
Because you don't, unspecified value applies, which means every read returns some arbitrary value, and not neccessarily the same.
All quotes are from draft n1570, C99+Ammendments aka C11.
Inconsistency in uninitialized boolean variable
An uninitialiazed variable is just a piece of raw memory and will show as value whatever happes to be there. You idea that "In the live system it always happens to be true" is totally wrong. All you can say is that every time you observed it in the live system it seemed to be true. May be on next Tuesday instead it will happen to be false because it's well known that uninitialized bools hate tuesdays.
Note that's even entirely possible that an uninitialized boolean may seem true for one function and false for another (normally a full byte is allocated for a bool, but only a bit is needed to represent the value: it's possible that an uninitialized bool will contain a magic fuzzy bool value that it's true for someone and false for someone else).
As for what the standard says accessing an uninitialized variable for reading may indeed be undefined behavior, with no limits on what may happen including crashes (and for example is easy to have a program to "stop" when reading an uninitialized variable, just compile with a specific tool for tracking this kind of problem). Always having a program crash on accessing an uninitialized variable would be wonderful, but unfortunately it's quite costly on current CPUs and it's not going to happen unless specific tools are used.
Of course adding even just a printf
call can change the apparent behavior of code handling uninitialized variables. This kind of bug is often referred to as "heisenbug" and actually the random or heisenbug behavior is often an indication of an uninitialized variable or of a thread synchronization problem.
What happens to a declared, uninitialized variable in C? Does it have a value?
Static variables (file scope and function static) are initialized to zero:
int x; // zero
int y = 0; // also zero
void foo() {
static int x; // also zero
}
Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.
void foo() {
int x;
printf("%d", x); // the compiler is free to crash here
}
In practice, they tend to just have some nonsensical value in there initially - some compilers may even put in specific, fixed values to make it obvious when looking in a debugger - but strictly speaking, the compiler is free to do anything from crashing to summoning demons through your nasal passages.
As for why it's undefined behavior instead of simply "undefined/arbitrary value", there are a number of CPU architectures that have additional flag bits in their representation for various types. A modern example would be the Itanium, which has a "Not a Thing" bit in its registers; of course, the C standard drafters were considering some older architectures.
Attempting to work with a value with these flag bits set can result in a CPU exception in an operation that really shouldn't fail (eg, integer addition, or assigning to another variable). And if you go and leave a variable uninitialized, the compiler might pick up some random garbage with these flag bits set - meaning touching that uninitialized variable may be deadly.
Related Topics
"X Does Not Name a Type" Error in C++
How Do Conversion Operators Work in C++
Throw Keyword in Function'S Signature
Is Sizeof in C++ Evaluated At Compilation Time or Run Time
How to Write a Short Literal in C++
Does Const-Correctness Give the Compiler More Room For Optimization
Overloading ++ For Both Pre and Post Increment
Confused When Boost::Asio::Io_Service Run Method Blocks/Unblocks
C++: Const Reference, Before VS After Type-Specifier
Is It a Good Practice to Place C++ Definitions in Header Files
A Free Tool to Check C/C++ Source Code Against a Set of Coding Standards