是否允许跳转到内部作用域或同级作用域内的标签?如果是这样,是否允许使用在该范围内声明的变量?
考虑这段代码:
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
合法吗?
如果是这样,当我跳转到
y
并保持分配给它的最后一个值时,label
是否保证存在(2
)?
或者编译器是否允许假设
y
在超出范围后不会被使用,这意味着单个内存位置可以同时用于 y
和 z
?
如果此代码的行为未定义,我怎样才能让 GCC 发出有关它的警告?
来自C99标准(强调我的):
6.2.4 对象的存储时长
[6] 对于这样一个具有可变长度数组类型的对象,它的生命周期从对象的声明开始延伸,直到程序的执行离开声明的范围。 ...如果递归地输入范围,则“每次都会创建一个新的对象实例”。对象的初始值是不确定的。
6.8.6.1[1]
goto
声明goto
语句中的标识符应命名位于
封闭函数中某处的标签。goto
语句不得从具有 可变修改类型的标识符的范围之外跳转到该标识符的范围内。[4] ...goto
语句不允许跳过任何具有可变修改类型
的对象声明。结论
y
可变修改类型
,因此,根据标准,跳跃是合法。
y
y = 2
),因此
y
的值是不确定
。您可以使用
-Wjump-misses-init
警告
,如下所示:
warning:
jump skips variable initialization [-Wjump-misses-init]
y
跳转是合法的(在 C 中,在 C++ 中则不是)。