是否允许跳转到内部范围或兄弟范围内的标签?如果是这样,是否允许使用在该范围内声明的变量?
考虑以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
这些goto合法吗?
如果是这样,y当我跳转label并保持分配给它的最后一个值(2)时,保证存在?
或者允许编译器假设y在超出范围后不会被使用,这意味着单个内存位置可以用于y和z?
如果此代码的行为未定义,我如何让GCC发出警告?
从C99标准(强调我的):
6.2.4对象的存储持续时间
[6]对于具有可变长度数组类型的对象,其生命周期从对象的声明扩展,直到程序的执行离开声明的范围....如果以递归方式输入范围,则每次都会创建该对象的新实例.对象的初始值是不确定的.
6.8.6.1
goto声明[1]
goto语句中的标识符应命名位于封闭函数中某处的标签.甲goto陈述,不能从具有一个标识符的范围之外跳可变类型到该标识符的范围内.[4] ...
goto不允许语句跳过具有可变修改类型的对象的任何声明.
y不是一种可变的修改类型,因此,根据标准,跳跃是合法的.
y保证存在,但跳转跳过initial(y = 2),因此值y是不确定的.
您可以使用-Wjump-misses-initGCC发出如下警告:
warning:jump skips variable initialization [-Wjump-misses-init]
在C++中,跳转是不合法的,C++不允许跳过初始化y.
跳转是合法的(在C中,在C++中它们不是).
为
y保证当我跳到存在label
是.
并保持分配给它的最后一个值(
2)?
没有.
对于没有可变长度数组类型的此类对象[没有存储类说明符static],其生命周期从entry进入与其关联的块,直到该块的执行以任何方式结束.[...]对象的初始值是不确定的.如果为对象指定了初始化,则每次在执行块时达到声明[...]时执行初始化; 否则,每次达到声明时,该值将变为不确定.
从上面的人会得出结论的为第2和第3次use(y)被调用的值y项" 不确定[d] ",为的初始化y时不 " 达 ".