The behavior of the for loop split between switch cases

While playing with the code I’ve noticed a strange behavior that I do not know to explain the logic behind

int foo(int n)
{
    int m = n;
    while (--n > 0)
    {
        switch (n)
        {
            case -1:
            case 0:
                for (int j = 0; j < m; ++j)
            default:
                    printf(":-)");
                break;
        }
    }
}

int main()
{
    foo(10);
    return 0;
}

I would expect the printf to execute let’s say 10 times. Then I saw it continues to run (imagine 100000 instead of 10) and supposed that the developers (VS) interpreted the printf inside the for (pretty expected), hence the output is made n times for each entrance to switch.

But then turned out j was never initialized.

So my question is why ? Is this an undefined behavior? Is not this a, supposedly, standard code?

Answer

default is just a label (address to where the code jumps if n is not -1 or 0). Thus when n is not -1 or 0, the flow enters the body of the for loop skipping the initialisation of j. You can write the same code also as this, so it would be clearer what is happening here:

int m = n;
while (--n > 0)
{
    switch (n)
    {
        case -1:
        case 0:
            for (int j = 0; j < m; ++j)
            {
        default: printf(":-)");
            }
            break;
    }
}

(Note, as mentioned by @alagner in the comments, it won’t compile with C++ compiler but perfectly compiles with C one so this is good enough to make my point and explain how the code looks).

So yes, since j is uninitialised, it is undefined behaviour. If you enable compiler warnings, it will warn you about it (https://godbolt.org/z/rzGraP):

warning: 'j' may be used uninitialized in this function [-Wmaybe-uninitialized]
   12 |                 for (int j = 0; j < m; ++j)
      |                          ^                  

Leave a Reply

Your email address will not be published. Required fields are marked *