13

In the following code, the variable has no initial value and printed this variable.

int var;
cout << var << endl;

output : 2514932

double var;
cout << var << endl;

output : 1.23769e-307

I don't understand these output numbers. Can any one explain this to me?

Donald Duck
  • 6,488
  • 18
  • 59
  • 79
cmuse
  • 275
  • 1
  • 3
  • 7
  • 3
    When you compile this code. Does the compiler not generate a lot of warnings about uninitialized variables? If you set your compiler to treat warnings as errors (a good idea) and also increase the warning level then it will not compile and you will build safer code (warnings are usually logical errors). – Martin York Nov 23 '10 at 19:24
  • yes, i compile this code with gcc on ubuntu. it was not any warning. – cmuse Nov 23 '10 at 19:26
  • 2
    @cmuse - compile with `-Wall`, will help you spot more warnings. And this issue will pop up once you use that flag. `gcc -Wall source.c -o myexecutable` – wkl Nov 23 '10 at 19:30
  • 3
    What values did you expect your program to print instead? – Rob Kennedy Nov 23 '10 at 19:33
  • @Rob Kennedy - i don't expect anything. i was curious what it is. – cmuse Nov 23 '10 at 19:43
  • I'm adding this to the C++ FAQ because we don't have an uninitialized variables question, and my answer gives the canonical and technical reasons for results. – GManNickG Mar 29 '11 at 21:47

6 Answers6

35

Put simply, var is not initialized and reading an uninitialized variable leads to undefined behavior.

So don't do it. The moment you do, your program is no longer guaranteed to do anything you say.


Formally, "reading" a value means performing an lvalue-to-rvalue conversion on it. And §4.1 states "...if the object is uninitialized, a program that necessitates this conversion has undefined behavior."

Pragmatically, that just means the value is garbage (after all, it's easy to see reading an int, for example, just gets random bits), but we can't conclude this, or you'd be defining undefined behavior.

For a real example, consider:

#include <iostream>

const char* test()
{
    bool b; // uninitialized

    switch (b) // undefined behavior!
    {
    case false:
        return "false";      // garbage was zero (zero is false)
    case true: 
        return "true";       // garbage was non-zero (non-zero is true)
    default:
        return "impossible"; // options are exhausted, this must be impossible...
    }
}

int main()
{
    std::cout << test() << std::endl;
}

Naïvely, one would conclude (via the reasoning in the comments) that this should never print "impossible"; but with undefined behavior, anything is possible. Compile it with g++ -02.

Community
  • 1
  • 1
GManNickG
  • 459,504
  • 50
  • 465
  • 534
  • Are you sure the results are undefined rather than unspecified? Dereferencing an uninitialized pointer should definitely be undefined of course. But isn't it just unspecified what value an uninitialized variable has? – Omnifarious Nov 23 '10 at 23:26
  • @Omni: I've clarified in the answer. – GManNickG Nov 23 '10 at 23:42
  • 1
    +1 - A most excellent clarification. I feel embarrassed sometimes because I don't know the full ramifications of things I wouldn't do in the first place. :-) Though, I should've realized because I was thinking about what might happen if the `double` ended up with garbage in it that would normally be impossible for a `double` to have in it thereby violating an invariant of the `double` type. Demonstrating that with `bool` is much easier and more dramatic. – Omnifarious Nov 24 '10 at 00:11
  • This is printing `"false"` in g++ 4.9 and 5.1, how was it supposed to print `"impossible"`? – Lorenzo Pistone Nov 23 '15 at 20:15
  • @LorenzoPistone: On older versions of g++ this printed "impossible", I cannot quite recall what optimizations were applied (I think it tried to simplify the switch by removing branches it could assume wouldn't be taken, and it could assume both the `false` and `true` branches weren't taken because of UB), but they seem to have finally changed. – GManNickG Nov 24 '15 at 06:10
4

When you do:

int var;

You are only declaring an integer named var. You do not initialize it with a value, so in whatever location var is, will be garbage data.

int var = 5;

Would declare var and initialize it to 5.

See more: http://en.wikipedia.org/wiki/Uninitialized_variable

wkl
  • 68,357
  • 14
  • 154
  • 169
3

What you're getting is whatever data happened to be on the stack in the place the compiler decided that variable should go interpreted as an integer or a double. It will probably be the same each and every time your program runs because programs generally behave deterministically. Though there are also many cases in which it will end up not being the same from run-to-run of your program. If you change your program in the slightest, or have it make decisions based on user input before you get to that code you may or may not get different numbers.

Basically the value of a variable you haven't initialized is unspecified and may be absolutely anything. There is no rhyme or reason to what's there. Using a variable that is uninitialized is (formally speaking) undefined behavior and may result in all manner of strange things.

Doing this is generally bad practice. You want programs that behave in a predictable fashion, and having uninitialized variables is a source of unpredictability. Note that it is most emphatically not a source of randomness, just unpredictability. Most compilers will complain about code like that if you turn on all the warnings.

Omnifarious
  • 50,447
  • 15
  • 117
  • 181
  • I'm sorry, but it will not be the same even if the program assigns the memory address offset deterministically, because the memory might have been used by some other program or the base address of your program may have changed. – Bruno Brant Nov 23 '10 at 20:00
  • @Bruno Brant - This is true. In many cases it will be the same, and likely in the case of the OP. But I should update my answer with this detail. – Omnifarious Nov 23 '10 at 20:23
2

In C++, when you declare a variable, the compiler assigns a memory address to it. And that's it, no cleanup is done. This is mostly because C++ (and C) where build with performance in mind. C++ doesn't spend time initializing an address unless you tell it explicitly to do so.

And the so called garbage you see is whatever it was left at that address by the last variable that used it.

Other languages will initialize the data for you. In fact, C# won't let you use the variable until you initialize it. Those languages are designed to be safe, in a sense that it won't let you write a code that mistakenly uses an uninitialized address and crash your program or, worse, corrupt your data.

Bruno Brant
  • 7,558
  • 5
  • 40
  • 76
1

you didn't initialize var in either case so you get garbage output.

had you done

const int var(5);

it would be initialized with the value 5

Sam Miller
  • 22,843
  • 3
  • 61
  • 85
1

When you declare var it gets assigned a location in memory. However, that memory isn't set to anything by default, so you pick up whatever was there before. This will be some garbage value that has no meaning.

In C++ this is true for both member variables and local variables. However, in languages like Java and C# your member variables are automatically initialized to 0 for numberic types, false for booleans and null for references. This isn't done for local variables and (at least in the C# compiler) your build will fail if you attempt to take the value of an un-initialized variable.

Sean
  • 55,981
  • 11
  • 86
  • 129