16

I am confused about the following code:

#include <iostream>

int i = 1;
int main()
{
    int i = i;
    std::cout << "i: " << i << "\n";
    return 0;
}

Output:

i: 0

I had expected running the above code would print 1. Can someone please explain the reason for this strange behavior?

James Ko
  • 32,215
  • 30
  • 128
  • 239
Ren
  • 2,852
  • 2
  • 23
  • 45
  • 24
    When strange things happen, it's usually UB. – Maroun Mar 20 '16 at 14:10
  • 15
    The warning "main.cpp:13:13: Variable 'i' is uninitialized when used within its own initialization: given by a reasonable compiler may be a hint as to the problem. Perhaps jam up your warning levels and heed their advice. – WhozCraig Mar 20 '16 at 14:11
  • 3
    When you assign int i= i;, i gets initialized with the value of i which you just declared, hence an undefined value. –  Mar 20 '16 at 14:20
  • 4
    Please, always compile with `-Wall -Werror` – temoto Mar 20 '16 at 15:34
  • @temoto: none of `g++ -Wall -Wextra`, `clang -Weverything`, MSVC `/Wall /Wextra /Weverything` warns about this. – GingerPlusPlus Mar 20 '16 at 18:16
  • 2
    aside: just in case you are not familiar with [undefined behavior](http://www.slideshare.net/GiorgiMoniava/introduction-to-undefined-behavior-in-c-and-c) – Giorgi Moniava Mar 20 '16 at 18:32
  • @GingerPlusPlus -- I don't have MSVC, but I do have clang and g++, and both of them issue warnings about `i` being used uninitialized. – David Hammen Mar 20 '16 at 19:01
  • @DavidHammen: I guess I just use outdated versions, then. – GingerPlusPlus Mar 20 '16 at 19:18

1 Answers1

62

You are initializing i with itself. The both i's in int i = i; are the inner one not the outer one. This is undefined behavior and you may get 0 or anything may happen.

This is the right way if you want to assign the outer i to the inner i.

#include <iostream>

int i = 1;
int main()
{
    int i = ::i;
    std::cout << "i: " << i << "\n";
    return 0;
}

Live Demo


BTW, You should carefully read all the compiler warnings. If you did you could see the problem yourself:

warning 'i' is used uninitialized in this function

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160
  • 5
    Do you have any snippets from the standard that support the claim that int i = i; is in fact undefined behavior. An uninitialized variable is not undefined behavior it just has an unspecified value. And since this exact construction appears in the standard (3.3.2) with a claim that the value will be indeterminate, I'm highly skeptical that this is UB. – Steve Cox Mar 20 '16 at 19:03
  • @SteveCox I don't think this is undefined behavior because there is no arithmetic being performed. Using `i` as the denominator in a division operation *may* result in undefined behavior depending on various factors. – Corey Mar 20 '16 at 23:36
  • @johannes, there is a difference between unspecified and undefined behaviour. Unspecified means it has to do something vaguely sensible, but not crash, and definitely no time portals. I think this *could* be either undefined or unspecified though, so it'd be nice to see where in the standard it says this. – tobyodavies Mar 21 '16 at 00:51
  • @SteveCox: There's special permission for narrow character types which make the result uninitialized. The example in 3.3.2 uses `unsigned char` which is a narrow character type. But this code uses `int`, ergo it requires lvalue->rvalue conversion on an uninitialized value, which causes undefined behavior. See 8.5p12 "If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases" (all cases require a narrow character type) – Ben Voigt Mar 21 '16 at 03:14
  • 2
    @SteveCox: Please see http://stackoverflow.com/q/23415661/103167 – Ben Voigt Mar 21 '16 at 03:23
  • @BenVoigt Thanks for the reference. Looks like this did change in the c++11 standard. i should probably get that – Steve Cox Mar 21 '16 at 15:21