C語言switch case語句中定義變數問題
阿新 • • 發佈:2019-01-09
這個問題需要分開討論,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 之前那塊地方也就只能寫寫這樣的宣告,寫別的表示式,賦值啊什麼的,統統是不會生效的。