编译程序时,编译器报错
error: jump to case label [-fpermissive] , error: crosses initialization of 'xxxx'
,对相关内容进行简单的梳理
一、问题代码
int main()
{
int test = 2;
switch(test)
{
case 1:
int i = 1; // i初始化后,一直存在,直到switch结束
cout << i;
break;
case 2:
cout << i; // i未被初始化
break;
default:
cout << "error" << endl;
}
}
#报错信息如下
//test.cpp: In function 'int main()':
//test.cpp: error: jump to case label [-fpermissive]
// case 2:
// ^
//test.cpp: error: crosses initialization of 'int i'
// int b = 1;
//test.cpp: error: jump to case label [-fpermissive]
// default:
// ^
//test.cpp:11:8: error: crosses initialization of 'int i'
// int b = 1;
二、说明
从上面的代码中可以看出,因为switch中没有单独的区域块来限定变量i的声明周期,所以变量的作用域是初始化点到switch的结尾处。这里由于我们无法确定其他case中是否会使用到这种变量,使用之前变量是否被初始化,所以编译器会报错。例如:test值为2,直接执行case 2的话,未定义变量就会出异常。这也是编译器报错crosses initialization
的原因。
经过检验发现,无论其他分支是否包含定义的变量,只要case中带变量不带括号,编译器都会报错
。
int main()
{
int test = 2;
switch(test)
{
case 1:
int i = 1;
cout << i;
break;
case 2:
cout << 3; // 同样会报错
break;
default:
cout << "error" << endl;
}
}
#报错信息如下
//test.cpp: In function 'int main()':
//test.cpp: error: jump to case label [-fpermissive]
// case 2:
// ^
//test.cpp: error: crosses initialization of 'int i'
// int i = 1;
//test.cpp: error: jump to case label [-fpermissive]
// default:
// ^
//test.cpp: error: crosses initialization of 'int i'
// int i = 1;
三、修改方法
1、【缩小作用域】将case 1的代码用{ }括起来,设定清楚变量i的作用域,避免其他case访问
2、【扩大作用域】将变量i放到switch外部,switch中的每个case都可以访问
四、深入了解
switch语句是goto语句的一种,所以goto具备相同的性质,下述的goto语句不会被执行,变量i一定会被定义,但是会报跟上面一样的错误。这说明goto与标签之间,不能出现变量。变量必须出现在goto之前或标签之后。
int main()
{
if(0)
{
goto end;
}
int i = 1;
end:
cout << i;
}
#报错信息如下:
//test.cpp: In function 'int main()':
//test.cpp error: jump to label 'end' [-fpermissive]
// end:
// ^
//test.cpp error: from here [-fpermissive]
// goto end;
// ^
//test.cpp: error: crosses initialization of 'int i'
// int i = 1;
上述例子,将变量的初始化放在goto标签之前,或者end标签之后,都是可以的