Switch-case 內定義變量的問題


Switch-case 內定義變量的問題

這個問題需要分開討論,C 語言和 C++ 的標准定義是不同的。

C++

int Caset(int a) {
    switch (a) {
        case 1:
            int b = 1;
            std::cout<<"a==1: "<<b<<std::endl;
            break;
        case 2:
            b = 2;
            std::cout<<"a==2: "<<b<<std::endl;
            break;
    }
}

編譯報錯信息為

simple.cc:35:9: error: cannot jump from switch statement to this case label
        case 2:
        ^
simple.cc:32:17: note: jump bypasses variable initialization
            int b = 1;
                ^

也就是說,跳到 case2 的這個地方,忽略了對於 b 這個變量的初始化,這個很直觀,就是在這里我找不到 b。

那么如果改成

int Caset(int a) {
    switch (a) {
        case 1:
            int b;
            b = 1;
            std::cout<<"a==1: "<<b<<std::endl;
            break;
        case 2:
            b = 2;
            std::cout<<"a==2: "<<b<<std::endl;
            break;
    }
}

順利成功,沒有報錯,如果 a 為 2,那么輸出 b 也是 2,說明邏輯沒有問題。那么問題來了,b 在前面聲明,為什么后面可以用到呢,因為 switch-case 的邏輯控制就是用 label 來標記跳轉的,而不是別的復雜的邏輯控制,所以 b 的作用域是在整個 switch 的花括號內,關於這個問題見知乎討論請教switch內部的變量定義問題

C 語言

上面兩種寫法統統出錯,

void Caset(int a) {
    switch (a) {
        case 1:
            /* one style */
            int b;
            b = 1;
            
            /* another style */
            int b = 1;

            printf("1: %d", b);
            break;
        case 2:
            b = 2;
            printf("2: %d", b);
            break;
    }
}

兩種寫法都錯

First style:

main.c:12:13: error: expected expression
        int b; 
        ^
main.c:13:13: error: use of undeclared identifier 'b'
        b = 1;
        ^

Another style:

ttt.c:11:13: error: expected expression
        int b = 1;
        ^

意思是說,此處需要一個表達式(expression),而不是一個變量聲明初始化。有一個很黑客的做法,如下:

void Caset(int a) {
    switch (a) {
        case 1:
            ; 
            int b = 1;
            // b = 1;

            printf("1: %d \n", b);
            break;
        case 2:
            b = 2;
            printf("2: %d \n", b);
            break;
    }
}

這個很不能理解了,其實也就是說保證 case 后面跟着的確實是 expression 即可。考慮一下 C++ 代碼出現的問題:跳過變量的聲明?C 語言中同樣跳過,但是編譯器不認為這個是錯誤,而且邏輯上面也是沒有問題的,在后面的 case 中可以正常給變量賦值,但是如果 case2 中,我不是給 b 賦值,而是直接訪問 b,那返回的數值就是一個隨機的錯誤的數據了,我在我的電腦上使用 gcc 編譯,若直接讀取數據,得到的是 0,當然編譯通過,連警告都沒有。

總結起來就是:

  1. C 編譯器允許一個 case 使用另一個 case 后聲明定義的變量,但是 C++ 語法不允許這個
  2. C 不允許 case 后面緊跟聲明或定義,只允許表達式(expression); C++ 對這個沒有限制

通用解法

當然我認為這樣的代碼可讀性差,比較好的做法可以是將聲明變量的事情放在頭上做。

void Caset(int a) {
    switch (a) {
        int b;
        case 1:
            b = 1;
            // b = 1;
            printf("1: %d \n", b);
            break;
        case 2:
            b = 2;
            printf("2: %d \n", b);
            break;
    }
}

但是要留心, switch 和 case 之前那塊地方也就只能寫寫這樣的聲明,寫別的表達式,賦值啊什么的,統統是不會生效的


參考:

Why can't variables be declared in a switch statement?這個鏈接中我個人比較推薦 AnT 的回答,講清楚了問題的原因和解決方案的原理


免責聲明!

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



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