跳过变量初始化格式错误还是会导致未定义的行为?
Is jumping over a variable initialization ill-formed or does it cause undefined behaviour?
考虑这段代码:
void foo()
{
goto bar;
int x = 0;
bar: ;
}
GCC 和 Clang reject it,因为跳转到 bar:
绕过了变量初始化。 MSVC 根本没有抱怨(除了在 bar:
之后使用 x
会导致警告)。
我们可以用 switch
:
做类似的事情
void foo()
{
switch (0)
{
int x = 0;
case 0: ;
}
}
现在所有三个编译器 emit errors。
这些片段格式不正确吗?还是它们会导致 UB?
我曾经认为两者都是错误的,但我找不到标准的相关部分。 [stmt.goto] doesn't say anything about this, and neither does [stmt.select].
当初始化是非空的时,它是病式的。
[stmt.dcl]
3 It is possible to transfer into a block, but not in a way that
bypasses declarations with initialization (including ones in
conditions and init-statements). A program that jumps from a point
where a variable with automatic storage duration is not in scope to a
point where it is in scope is ill-formed unless the variable has
vacuous initialization ([basic.life]). In such a case, the variables
with vacuous initialization are constructed in the order of their
declaration.
初始化程序使初始化非空。相比之下,这个
void foo()
{
goto bar;
int x; // no initializer
bar: ;
}
将是合式的。尽管有关使用具有不确定值的 x
的通常注意事项将适用。
If transfer of control enters the scope of any automatic variables
(e.g. by jumping forward over a declaration statement), the program is
ill-formed (cannot be compiled), unless all variables whose scope is
entered have
- scalar types declared without initializers
- class types with trivial default constructors and trivial destructors declared
without initializers
- cv-qualified versions of one of the above
- arrays of one of the above
考虑这段代码:
void foo()
{
goto bar;
int x = 0;
bar: ;
}
GCC 和 Clang reject it,因为跳转到 bar:
绕过了变量初始化。 MSVC 根本没有抱怨(除了在 bar:
之后使用 x
会导致警告)。
我们可以用 switch
:
void foo()
{
switch (0)
{
int x = 0;
case 0: ;
}
}
现在所有三个编译器 emit errors。
这些片段格式不正确吗?还是它们会导致 UB?
我曾经认为两者都是错误的,但我找不到标准的相关部分。 [stmt.goto] doesn't say anything about this, and neither does [stmt.select].
当初始化是非空的时,它是病式的。
[stmt.dcl]
3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization (including ones in conditions and init-statements). A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has vacuous initialization ([basic.life]). In such a case, the variables with vacuous initialization are constructed in the order of their declaration.
初始化程序使初始化非空。相比之下,这个
void foo()
{
goto bar;
int x; // no initializer
bar: ;
}
将是合式的。尽管有关使用具有不确定值的 x
的通常注意事项将适用。
If transfer of control enters the scope of any automatic variables (e.g. by jumping forward over a declaration statement), the program is ill-formed (cannot be compiled), unless all variables whose scope is entered have
- scalar types declared without initializers
- class types with trivial default constructors and trivial destructors declared without initializers
- cv-qualified versions of one of the above
- arrays of one of the above