0

I barely start my c++ learning. I have met a strange case that I cannot understand. It's about declaring and printing a double variable.

My first piece of code looks like below:

#include <iostream>

int main ()
{
    double wage;
    std::cout << wage << std::endl;
    return 0;
}

After I compile this file with g++ and run it, there is a 0 printed in my terminal, which is fine. Then I keep adding lines of code and now it looks like this:

#include <iostream>

int main ()
{
    double wage;
    std::cout << wage << std::endl;
    double salary = wage = 9999.99;
    std::cout << wage << std::endl;
    std::cout << salary << std::endl;
    std::cout << wage
              << salary << std::endl;
    return 0;
}

However, when I try to compile and run this program again, a very strange decimal appears.

$ cpp-directory ./a.out
2.122e-314
9999.99
9999.99
9999.999999.99

As you can see from the result, there is a 2.122e-314. From my perspective, it should print 0 on the first line rather than this number... I am not familiar with c++ stuff but is it something like a memory leak or so...

Can someone give me a tip or an explanation on this? Thanks.

Note:

$ ~ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Kulbear
  • 871
  • 2
  • 10
  • 24
  • 4
    You’re trying to use an uninitialized variable. If you want zero, initialize it with `double wage = 0`. – Ry- May 31 '17 at 21:00
  • @Ryan I know I am using an uninitialized variable, but I don't understand why this happened? – Kulbear May 31 '17 at 21:01
  • 1
    Because uninitialised variables do not necessarily contain zero - probably they won't. –  May 31 '17 at 21:02
  • You should consider learning about `execution stack` and how it grows, shrinks over a period of the program's execution – Zakir May 31 '17 at 21:04
  • 1
    `-Wall -Wextra -Werror` repeat after me `-Wall -Wextra -Werror` good, now again: `-Wall -Wextra -Werror` well done! one more time: `-Wall -Wextra -Werror` great! now never forget it! – bolov May 31 '17 at 21:12
  • @bolov clapping – Kulbear May 31 '17 at 21:13

2 Answers2

4
int main ()
{
    double wage;
    std::cout << wage << std::endl;//Undefined Behavior!
    return 0;
}

You haven't initialized wage with a value, which means that its value will be whatever happened to occupy those bytes before your program entered this stack frame. If you attempt to use the value (in any way other than writing to it) the program will read that garbage value and interpret it as a double. In some situations, that memory will be initialized to 0. In other situations, it could be initialized to literally anything. If you want to guarantee that you get a value of 0, you need to explicitly set it as such:

int main ()
{
    double wage = 0;
    std::cout << wage << std::endl;//Perfectly Defined Behavior!
    return 0;
}
Xirema
  • 19,889
  • 4
  • 32
  • 68
  • So it is given with a random value here? – Kulbear May 31 '17 at 21:02
  • @Kulbear "Random" has a meaning in this context I'm hesitant to endorse the use of. But yes, the value is not guaranteed to have any particular default value unless you explicitly set it to a value in code, or explicitly default-initialize it like `double wage{};`. – Xirema May 31 '17 at 21:03
  • OK, it makes sense. So I declare this double and then there is an address assigned to this variable, but without giving an initialized value, it is containing the previous byte value from the memory stack right? – Kulbear May 31 '17 at 21:04
  • @Kulbear Yup! Some compilers, in DEBUG mode, will add instructions to clear the value of the variable before any instructions otherwise make use of it, but you should never rely on that behavior! – Xirema May 31 '17 at 21:05
1

The behaviour on outputting (i.e. reading) the value of an uninitialised double type variable is undefined. It's pointless trying to account for the output - you can always check the generated assembly which might yield some clues as to what the compiler has done.

The compound assignment in the second snippet is valid and the two numbers are concatenated in the final output.

Some languages (e.g. various incarnations of BASIC) do zero initialise variables, but C++ is not one of them.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483