前言
goto语句也称为无条件转移语句,其基本形式如下 :
语句标号由一个有效地标识符和符号";"组成,其中,标识符的命名规则与变量名称相同,即由字母、数字和下划线组成,且第一个字符必须是字母或下划线。执行goto语句后,程序就会跳转到语句标号处,并执行其后的语句。
通常goto语句与if条件语句连用,但是,goto语句在给程序带来灵活性的同时,也会使得使程序结构层次不清,而且不易读,所以要合理运用该语句。
发现问题
我们经常碰到有在goto后面定义变量,linux下编译不通过的问题(报错信息:crosses initialization of)。其实,只要注意一下就好了,今天问了一下公司前辈之后,也翻了些资料,记录一下,加深记忆,也希望能对一些人有些许帮助。
错误示例代码:
#include <iostream>
using namespace std;
int main()
{
goto Exit;
int a = 0;
Exit:
return 0;
}
报错:
[root@localhost c-c++]# g++ goto_study.cpp
goto_study.cpp: In function 'int main()':
goto_study.cpp:31: error: jump to label 'Exit'
goto_study.cpp:29: error: from here
goto_study.cpp:30: error: crosses initialization of 'int a'
正确写法
也不能说是正确的写法,只能说是编译OK的写法。
直接上代码:
写法一:
改变域,变成局部变量:
int main()
{
goto Exit;
{
int a = 0;
}
Exit:
return 0;
}
写法二
神奇的写法:
int main()
{
goto Exit;
int a;
a = 1;
Exit:
cout << "a = " << a << endl;
return 0;
}
关键是还可以访问!结果:
[root@localhost c-c++]# g++ goto_study.cpp
[root@localhost c-c++]# ./a.out
a = 1259648
研究
神奇的写法
看到两个可以编译通过的写法之后,最纳闷的是写法二为毛可以编译通过,而且还能使用???
C++规定
参考[1][2]中提到了C++标准中的规定: > 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 local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer.
意思是说:如果一个程序的执行路径从代码中的点A(某个局部变量x还未定义)跳到代码中另一点B(该局部变量x已定义,并且定义的时候有初始化),那么编译器会报错。这样的跳跃可以是由于执行goto语句,或者是switch-case造成的。所以,在写法二中a是int类型,是一个POD类型,并且没有初始化,所以编译通过。但是,很明显:如果去使用这个变量a的时候,结果是未知的,就像前辈说的,没有意义,还不如不支持!那如果只在局部使用,完全可以用花括号括起来!网上也有人说到,C++规范虽然没有明确说明这样是错误的,但是变量的域的规定其实是隐性说这种做法是不可取的,见参考[4]。










