1. 程式人生 > >C語言switch case語句中定義變數問題

C語言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;
    }
}

兩種寫法都錯,報錯資訊:

main.c:12:13: error: expected expression
    int b; 
    ^
main.c:13:13: error: use of undeclared identifier 'b'
    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,當然編譯通過,連警告都沒有。

當然我認為這樣的程式碼可讀性差,比較好的做法可以是將宣告變數的事情放在頭上做。

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 之前那塊地方也就只能寫寫這樣的宣告,寫別的表示式,賦值啊什麼的,統統是不會生效的。