语句goto不能跨变量定义? [英] Statement goto can not cross variable definition?

查看:32
本文介绍了语句goto不能跨变量定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设这些代码在g++中编译:

Suppose these code compiled in g++:

#include <stdlib.h>

int main() {
    int a =0;

    goto exit;

    int *b = NULL;

exit:
    return 0;
}

g++ 会抛出错误:

goto_test.c:10:1: error: jump to label ‘exit’ [-fpermissive]
goto_test.c:6:10: error:   from here [-fpermissive]
goto_test.c:8:10: error:   crosses initialization of ‘int* b’

似乎 goto 不能交叉指针定义,但 gcc 编译它们没问题,没有任何抱怨.

It seems like that the goto can not cross pointer definition, but gcc compiles them ok, nothing complained.

修复错误后,我们必须在任何goto语句之前声明所有指针,也就是说你必须声明这些指针,即使你现在不需要它们(并且违反有一些原则).

After fixed the error, we must declare all the pointers before any of the goto statement, that is to say you must declare these pointers even though you do not need them at the present (and violation with some principles).

g++ 禁止有用的tail-goto 语句的起源设计考虑是什么?

What the origin design consideration that g++ forbidden the useful tail-goto statement?

更新:

goto 可以跨变量(任何类型的变量,不限于指针)声明,但获得初始化值的除外.如果我们删除上面的 NULL 赋值,g++ 现在保持沉默.所以如果你想声明goto-cross-area之间的变量,不要初始化它们(仍然违反一些原则).

goto can cross variable (any type of variable, not limited to pointer) declaration, but except those that got a initialize value. If we remove the NULL assignment above, g++ keep silent now. So if you want to declare variables that between goto-cross-area, do not initialize them (and still violate some principles).

推荐答案

Goto 不能跳过变量的初始化,因为在跳转后相应的对象将不存在,因为具有非平凡初始化的对象的生命周期从那一刻开始执行初始化:

Goto can't skip over initializations of variables, because the respective objects would not exist after the jump, since lifetime of object with non-trivial initialization starts when that initialization is executed:

C++11 §3.8/1:

[…] T 类型对象的生命周期开始于:

[…] The lifetime of an object of type T begins when:

  • 获得了适合类型 T 的对齐方式和大小的存储,并且

  • storage with the proper alignment and size for type T is obtained, and

如果对象有非平凡初始化,则其初始化完成.

if the object has non-trivial initialization, its initialization is complete.

C++11 §6.7/3:

可以转移到块中,但不能通过初始化绕过声明.一个从具有自动存储持续时间的变量不在范围内的点跳转到它在范围内的点是格式错误的,除非变量具有标量类型,类类型具有微不足道的默认值构造函数和普通析构函数,其中一种类型的 cv 限定版本,或其中一种类型的数组前面的类型,并且在没有初始化程序的情况下声明 (8.5).

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. 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 scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5).

由于错误提及 [-fpermissive],您可以通过指定该编译器标志将其变为警告.这表明两件事.过去是允许的(变量会存在,但在跳转后未初始化)并且 gcc 开发人员认为规范禁止它.

Since the error mentions [-fpermissive], you can turn it to warning by specifying that compiler flag. This indicates two things. That it used to be allowed (the variable would exist, but be uninitialized after the jump) and that gcc developers believe the specification forbids it.

编译器只检查变量是否应该被初始化,而不检查它是否被使用,否则结果会很不一致.但是,如果您不再需要该变量,您可以自己结束它的生命周期,使tail-goto"变得可行:

The compiler only checks whether the variable should be initialized, not whether it's used, otherwise the results would be rather inconsistent. But if you don't need the variable anymore, you can end it's lifetime yourself, making the "tail-goto" viable:

int main() {
    int a =0;
    goto exit;
    {
        int *b = NULL;
    }
exit:
    return 0;
}

完全有效.

附带说明,该文件具有扩展名 .c,这表明它是 C 而不是 C++.如果你用 gcc 而不是 g++ 编译它,原始版本应该可以编译,因为 C 没有这个限制(它只有可变长度数组的限制——它在 C++ 中根本不存在).

On a side-note, the file has extension .c, which suggests it is C and not C++. If you compile it with gcc instead of g++, the original version should compile, because C does not have that restriction (it only has the restriction for variable-length arrays—which don't exist in C++ at all).

这篇关于语句goto不能跨变量定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆