編譯程序時,編譯器報錯
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標簽之后,都是可以的
