編譯程序時(shí),編譯器報(bào)錯(cuò)
error: jump to case label [-fpermissive] , error: crosses initialization of 'xxxx',對相關(guān)內(nèi)容進(jìn)行簡單的梳理
一、問題代碼
int main()
{
int test = 2;
switch(test)
{
case 1:
int i = 1; // i初始化后,一直存在,直到switch結(jié)束
cout << i;
break;
case 2:
cout << i; // i未被初始化
break;
default:
cout << "error" << endl;
}
}
#報(bào)錯(cuò)信息如下
//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;
二、說明
從上面的代碼中可以看出,因?yàn)閟witch中沒有單獨(dú)的區(qū)域塊來限定變量i的聲明周期,所以變量的作用域是初始化點(diǎn)到switch的結(jié)尾處。這里由于我們無法確定其他case中是否會使用到這種變量,使用之前變量是否被初始化,所以編譯器會報(bào)錯(cuò)。例如:test值為2,直接執(zhí)行case 2的話,未定義變量就會出異常。這也是編譯器報(bào)錯(cuò)crosses initialization的原因。
經(jīng)過檢驗(yàn)發(fā)現(xiàn),無論其他分支是否包含定義的變量,只要case中帶變量不帶括號,編譯器都會報(bào)錯(cuò)。
int main()
{
int test = 2;
switch(test)
{
case 1:
int i = 1;
cout << i;
break;
case 2:
cout << 3; // 同樣會報(bào)錯(cuò)
break;
default:
cout << "error" << endl;
}
}
#報(bào)錯(cuò)信息如下
//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的代碼用{ }括起來,設(shè)定清楚變量i的作用域,避免其他case訪問
2、【擴(kuò)大作用域】將變量i放到switch外部,switch中的每個(gè)case都可以訪問
四、深入了解
switch語句是goto語句的一種,所以goto具備相同的性質(zhì),下述的goto語句不會被執(zhí)行,變量i一定會被定義,但是會報(bào)跟上面一樣的錯(cuò)誤。這說明goto與標(biāo)簽之間,不能出現(xiàn)變量。變量必須出現(xiàn)在goto之前或標(biāo)簽之后。
int main()
{
if(0)
{
goto end;
}
int i = 1;
end:
cout << i;
}
#報(bào)錯(cuò)信息如下:
//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標(biāo)簽之前,或者end標(biāo)簽之后,都是可以的