3

When shadowing i inside the for loop, the following code

#include <stdio.h>

int main()
{
    for (int i = 1; i < 5; i++) {
        printf("%d", i);
        int i = i;
        printf("%d ", i);
    }
}

outputs:

10 20 30 40

From my understanding of shadowing, there should've been a new i created with the value equal to the previous i. This means the output I expected would've been:

11 22 33 44

Furthermore, the code seems to store the new i value if you increment it.

#include <stdio.h>

int main()
{
    for (int i = 1; i < 5; i++) {
        printf("%d", i);
        int i = i + 2;
        printf("%d ", i);
    }
}

this outputs:

12 24 36 48

Seemingly, i is not being redeclared every iteration - it works like a variable that was initially 0 and then was incremented every iteration.

What's actually happening here? How do you predict the behaviour?

7
  • 6
    Relevant: stackoverflow.com/questions/11186261/why-is-int-i-i-legal. Bottom line: int i = i; actually assigns i to itself (not the i of the loop`) and accessing it is UB. Commented Mar 6 at 17:29
  • @wohlstad that's talking about using a variable before it's initialised. But when you take int i = i here does the RHS refer to the for loop iterator or is it already shadowing there? Commented Mar 6 at 17:31
  • 2
    Since i is in scope within its own initialization, the RHS must be the "new" i which shadows the outer one. Commented Mar 6 at 17:34
  • @Lumin RHS is the new shadowing i. It is already in scope, othertwise a bare int i = i; wouldn't be legal. Commented Mar 6 at 17:34
  • MSVC issues a warning for both codes: uninitialized local variable 'i' used for the line int i = i; and int i = i + 2;. Commented Mar 6 at 17:39

2 Answers 2

4

A statement like:

int i = i;

Is generally legal, but unlike what you expect, will attempt to assign i to itself (and not to the i from the for loop).

This is because the new i is already in scope (otherwise a bare int i=i; without a previous i wouldn't be legal).

Afterwards you access this i which causes UB (undefine-behavior), which means that any result that you see is valid.

The same applies similarly to the case with:

int i = i + 2;

More about statements like int i = i; can be found here (that post is for C++ but is relevant for C as well).

Sign up to request clarification or add additional context in comments.

6 Comments

Why is the access "afterwards" UB, but not the one in the initializer?
@ikegami that's what I understood from the linked post. But you might be right (or at least there could be a minor difference between C and C++).
This is because the new i is already in scope (otherwise a bare int i=i; without a previous i wouldn't be legal). - it is completely wrong. The for loop i is unrelated here.
@0___________ can you explain why it is wrong ? I know the for loop is irrelevant. This is what I meant when I wrote that if in int i=i; the current i was not already in scope, than having a int i=i; without a prior i (from a for loop or any other) would not even compile (because the assigned i was not in scope yet). This means the curent i is indeed already in scope.
@wohlstad your claims are false: godbolt.org/z/61MrxY337
|
1

As mentioned elsewhere, int i = i; attempts to initialize i from itself, but the latter i refers to the new i, not the old one, and it has an unspecified value here, and, subject to certain conditions, this causes the program to have undefined behavior.

If you do wish to initialize a new i from the old one, you can do this with an intermediate variable:

#include <stdio.h>


int main(void)
{
    for (int i = 1; i < 5; i++)
    {
        printf("%d", i);
        int t = i, i = t;
        printf("%d ", i);
    }
    printf("\n");
}

Where t is initialized, the outer i is visible, and then the new i is initialized from t.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.