淺析C/C++中的switch/case陷阱


淺析C/C++中的switch/case陷阱

  先看下面一段代碼:

  文件main.cpp

#include<iostream>
using namespace std;


int main(int argc, char *argv[])
{
    int a =0;
    switch(a)
    {
        case 0: int b=1;cout<<b<<endl;break;
        case 1: cout<<b<<endl;break;
        default:break;
    }
    return 0;
}

  在gcc編譯器下編譯的結果為:

  提示跳過了變量b的初始化過程。對於一個局部變量,它的作用域為它所定義的地方到它所在的語句塊結束為止,那么對於變量b,它所在的最小語句塊為switch{}塊,那么也就說在case 0后面的部分,變量b都是可見的(注意在case 0之前變量b是無法訪問的)。考慮這樣一種情況,當a的值為1,那么程序就跳到case 1執行,此時b雖然可以訪問,但是跳過了它的初始化過程。而如果在定義變量的同時進行了初始化,表明程序員希望初始化這個變量,但是此時跳過了該變量的初始化,就可能導致程序出現程序員無法意料的情況,因此編譯器為了避免跳過這樣的初始化而造成無法預料的結果,就對該語句進行報錯。

  如果將上述代碼改為:

 switch(a)
    {
        case 0: int b;b=0;cout<<b<<endl;break;
        case 1: cout<<b<<endl;break;
        default: break;
    }

  編譯的結果為:

  只是進行了警告,因為在定義變量的時候沒有進行初始化,也就是說程序怎么執行都不會跳過變量的初始化過程,不會說由於跳過了該過程而造成無法預料的錯誤或程序崩潰現象。因此只是進行了警告。

  再看下面這段代碼:

 switch(a)
    {
        case 0: break;
        default: int b=1;cout<<b<<endl;break;
    }

  這段代碼沒有報錯。因為如果執行case 0,變量b沒有進行初始化,但是由於在case 0部分b是不可見的,因此不會對程序造成任何影響,而如果執行default分支,則b會被初始化,因此程序沒有報錯。

  歸根到底,出現上述的crosses initialization和jump to case label錯誤的原因是由於變量的作用域問題,因此一個好的習慣就是在case子句下面加上大括號來限定變量的作用域。

 switch(a)
    {
        case 0: {int b=1;cout<<b<<endl;break;}
        case 1: break;
        default: break;
    }

  不過要注意,一旦加上了大括號,在case 0后面便不能訪問到變量b了。

  注意,如果上述代碼以C方式進行編譯,編譯結果則會有所不同:

  main.c

#include <stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
    int a =2;
    switch(a)
    {
        
        case 0: int b=17;printf("%d\n",b);break;
        case 1: break;
        default:printf("%d\n",b);break;
    }
    return 0;
}

  編譯結果:

 

   報的錯誤意思是在該標簽下不能定義變量。為什么呢?原因很簡單,在C語言中所有的變量定義都必須放到所在語句塊的最前面。所以如果改成這樣:

#include <stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
    int a =2;
    switch(a)
    {
        int b=17;
        case 0: printf("%d\n",b);break;
        case 1: break;
        default:printf("%d\n",b);break;
    }
    return 0;
}

  編譯結果:

  沒有報錯,注意這里沒有報crosses initialization的錯誤,這點C和C++有點不同。如果以C++方式編譯,肯定會報crosses initialization的錯誤,這也更加說明C++在語法方面要求比C更加嚴格。

  該程序運行的結果:

  輸出32,是一個隨機值。因為b並沒有進行初始化,所以輸出的是隨機值。

  以上只是個人觀點,若有不正之處,懇請指正,以免誤導他人。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM