使用 goto 跳转到内部或兄弟范围

Using goto to jump to inner or sibling scope

是否允许跳转到内部范围或兄弟范围内的标签?如果是这样,是否允许使用在该范围内声明的变量?

考虑这段代码:

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;
}

这些 goto 合法吗?

如果是这样,当我跳转到 label 并保留分配给它的最后一个值 (2) 时,y 是否保证存在?

或者是否允许编译器假设 y 在超出范围后不会被使用,这意味着单个内存位置可以同时用于 yz?

如果此代码的行为未定义,我如何让 GCC 发出警告?

跳转是合法的(在 C 中,在 C++ 中它们不是)。

is y guaranteed to exist when I jump to label

是的。

and to hold the last value assigned to it (2)?

没有

来自C11 Standard (draft) 6.2.4/6

For such an object [without the storage-class specifier static] that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. [...] The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration [...] is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.

从上面可以得出结论,第 2 次和第 3 次 use(y) 被称为 y ins "indeterminate[d]" 的值, 因为 y 的初始化是 not "reached".

来自 C99 标准(强调我的):

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.

结论

  1. y 不是 可变修改类型 ,因此,根据标准,跳转是 合法的 .

  2. y保证存在,但是跳转跳过了初始化(y = 2),所以y的值为不确定.

  3. 您可以使用 -Wjump-misses-init 让 GCC 发出 警告,如下所示:

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


在C++中,跳转是不合法的,C++不允许跳过y的初始化。