是否允许跳转到内部范围或兄弟范围内的标签?如果是这样,是否允许使用在该范围内声明的变量?
考虑以下代码:
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
和{{1} }?
如果此代码的行为未定义,我如何让GCC发出警告呢?
答案 0 :(得分:9)
从C99标准(强调我的):



6.2.4对象的存储持续时间

 
[6]对于具有可变长度数组类型的对象,其生命周期从对象的声明扩展,直到程序的执行离开声明的范围。 ...如果以递归方式输入范围,则每次都会创建对象的新实例。对象的初始值是不确定的。

 
6.8.6.1

 
goto
语句[1]

 
goto
语句中的标识符应命名位于封闭函数中某处的标签。goto
语句不得从具有可变修改类型的标识符范围之外跳转到该标识符的范围内。[4] ...
&#xA; < / blockquote>&#xA;&#xA;goto
语句不允许跳过具有可变修改类型的对象的任何声明。结论
&#xA;&#xA;&#xA;
&#xA;&#xA;- &#xA;
y
不是a 可变修改类型,因此,根据标准,跳转是合法。<代码> y 保证存在,但跳转跳过初始化(
y = 2
),因此y
的值为 indeterminate < /strong>.- &#xA;
您可以使用
&#xA;&#xA;-Wjump-misses-init
让GCC发出警告如下所示:&#xA;&#xA;
警告:
跳转变量初始化[-Wjump-misses-init]
&#xA;&#xA;在C ++中,跳转不合法,C ++不允许跳过初始化
&#xA;y
。
答案 1 :(得分:7)
跳转是合法的(在C中,在C ++中它们不是)。
当我跳转到y
时,保证存在
label
是
并保留分配给它的最后一个值(
2
)?
没有
来自C11 Standard (draft) 6.2.4/6:
对于这样的对象[没有存储类 说明符静态],它没有可变长度数组类型,其生命周期延长 从进入与之关联的块直到该块的执行结束 无论如何。 [...]对象的初始值是不确定的。如果 为对象指定初始化,每次执行块时都会执行声明[...];否则,价值变为 每次达到声明时都不确定。
从上面可以得出结论,第二次和第三次use(y)
被称为y
ins“ indeterminate [d] ”的值,作为初始化y
不“到达”。