Home > Back-end >  c calling int twice
c calling int twice

Time:04-22

I was writing a code, and accidentally put int before a variable twice, and noticed something different in the end product.

int main ()
{
    int number = 123456789;
    int step = 0;

    while (number>0)
    {
        cout << number << endl;
        number = number/10;
        step = step 1;
        cout << "step ; " << step << endl;
    }

    return 0;
}

The output was:

9
step ; 1
8
step ; 2
7
step ; 3
6 ...

However, when I called it this way:

int main ()
{
    int number = 123456789;
    int step = 0;

    while (number>0)
    {
        cout << number << endl;
        number = number/10;
        int step = step 1;
        cout << "step ; " << step << endl;
    }

    return 0;
}

The output suddenly changed to:

9
step ; 11006125
8
step ; 11006126
7
step ; 11006127
6

Can someone please explain the difference, so that I will be mindful next time?

CodePudding user response:

C is block scoped. When you redeclare step inside the while loop (by using int step instead of just step), you "shadow" the step from outside that scope; while the outer step (with value 0) still exists, it cannot be read directly from the inner scope (a pointer/reference to the outer step with a different name could read/write the data, you just can't read the outer step directly through that name).

The outer step is invisible, so int step = step 1; translates as "please assign to the local step the value of whatever is already stored in the local step (which, not existing until that moment, has no defined value yet) after adding 1". Since the step it reads from is garbage, this is undefined behavior, and in practice, it gets garbage (whatever junk happened to be left on the stack in that position from before you entered the while).

The second and subsequent creations of the inner step are still undefined behavior, but in this case (and in most cases where loop unrolling isn't involved) the compiler chose to reuse the same storage for them as the prior use of inner step (that expired when that iteration of the loop ended). Thus, as a coincidence of the new inner step reading from the same memory location as the expired inner step, it increments normally from then on, based on the original garbage value as a base.

But again, to be clear, all of this is undefined behavior. Be thankful you didn't get nasal demons, and only use the first form in the future. I'll note, if you enable all warnings, any compiler worth its salt should detect this error (the entire error exists in the scope of a single line); sadly, it appears at least GCC is not worth its salt, because the only thing it detects, even with -Wall -Wextra -Werror -pedantic is that you didn't use the outer step variable. If you used it, or deleted the declaration of the outer step, it compiles with no warnings, so I guess you're stuck just remembering not to initialize a variable in terms of its own value.

CodePudding user response:

In the second case, you declare a second variable, which is also called step, but is visible only inside the loop.

  • Related