Search code examples
cloopsfor-loopscopeshadowing

Shadowing an iterator inside a for loop has undefined (?) behaviour in C


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?


Solution

  • 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).