Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using goto to jump to inner or sibling scope

Tags:

c

scope

goto

Is it allowed to jump to a label that's inside an inner scope or a sibling scope? If so, is it allowed to use variables declared in that scope?

Consider this code:

int cond(void);
void use(int);

void foo() 
{
    {
        int y = 2;
        label:
        use(y);
    }

    {
        int z = 3;
        use(z);

        /* jump to sibling scope: */ if(cond()) goto label;
    }

    /* jump to inner scope: */ if(cond()) goto label;
}

Are these gotos legal?

If so, is y guaranteed to exist when I jump to label and to hold the last value assigned to it (2)?

Or is the compiler allowed to assume y won't be used after it goes out of scope, which means a single memory location may be used for both y and z?

If this code's behavior is undefined, how can I get GCC to emit a warning about it?

like image 701
Spike Avatar asked May 22 '16 07:05

Spike


People also ask

Are goto labels scoped?

Labels are the only identifiers that have function scope: they can be used (in a goto statement) anywhere in the same function in which they appear.

What is the scope of goto?

A goto statement is allowed to jump within the scope of a variable length array, but not past any declarations of objects with variably modified types. The following example shows a goto statement that is used to jump out of a nested loop. This function could be written without using a goto statement.

Can goto jump between functions?

The goto statement can be used to jump from anywhere to anywhere within a function.

Why goto is forbidden?

"The GOTO statement is generally considered to be a poor programming practice that leads to unwieldy programs. Its use should be avoided."


1 Answers

From the C99 standard (emphasis mine):

6.2.4 Storage durations of objects

[6] For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration. ... If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.

6.8.6.1 The goto statement

[1] The identifier in a goto statement shall name a label located somewhere in the enclosing function. A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.

[4] ... A goto statement is not allowed to jump past any declarations of objects with variably modified types.

Conclusion

  1. y is not a variably modified type, so, according to the standard, the jumps are legal.

  2. y is guaranteed to exist, however, the jumps skip the initialization (y = 2), so the value of y is indeterminate.

  3. You can use -Wjump-misses-init to get GCC to emit a warning like the following:

    warning: jump skips variable initialization [-Wjump-misses-init]


In C++, the jumps are not legal, C++ does not allow to skip the initialization of y.

like image 62
sergej Avatar answered Oct 02 '22 17:10

sergej