switch語句中,case的後面為什麼必須是常量?

為什麼不能是變數?


因為C語言中的 switch 不是 if 的替代品。

編譯時會對 switch 進行優化,根據 case 標籤後面的常量值,生成跳轉表,只經過少數次數的比較,就可以跳到對應標籤下面。所以,標籤也是不能重複的。如果允許變數,switch 只能退化成跟一連串的 if else, 對於一個數據也只能從頭到尾地進行比較,也就失去了 switch 的意義。跳轉表和逐個比較,這兩種方式的複雜度差很多。

這也是 python 沒有引入和 C 語言裡面的 switch case 相對應的控制結構的一個原因。


看這 c++ - Why can switch only compare to const values?


下面是我的筆記,希望有用!

Any statement within the switch statement can be labeled with one or more case labels as follows: "case constant-expression :". where the constant-expression shall be a converted constant expression of the promoted type of the switch condition. No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.(來自C++標準)

討論:為什麼是case constant-expression:而不是case expression:?

可以避免二義性,Consider switch (c) { case a: ...; break; case b: ...; break; }. What would you expect to happen if a==b and b==c? 另外if the expression in label is not a constant, then it can"t determine where each value goes at compile-time.


from MDN

使用多條件 case 的方法(主要為方法二):

If you would like one case segment to meet multiple criteria there are two methods/tricks. Method one is the recommended way, method two is a "hacky" way. The two methods below aim to alert "yes" when variable foo is 0, 1, 2, or 3.

Sources for these techniques are here:

Multiple Criteria Single Case Switch Statement (Stack Overflow)Switch statement multiple cases in JavaScript (Stack Overflow)

方法一

This method takes advantage of the fact that if there is no break below a case statement it will continue to execute the next case statement regardless if the case meets the criteria. See the section title "What happens if I forgot a break?"

var foo = 1;
switch (foo) {
case 0:
case 1:
case 2:
case 3:
alert("yes");
break;
default:
alert("not");
}

方法二

This is the "hacky" method; on line 2, where you would usually find switch(foo), we instead put an invariant true, and place conditional logic (instead of constants) into the case statements:

var foo = 1;
switch (true) { // 非變數 TRUE 替代 foo
case foo &>= 0 foo &<= 3: alert("yes"); break; default: alert("not"); }


在大部分動態語言中,case後面是可以接變數甚至是表達式的。

比如說你可以這麼做:

var a = 0, b = 1, c = 3;
switch(true) {
case a &< b: alert("a比b小"); break; case a &< c: alert("a比c小"); break; }

基本上這種類型都可以用if else來寫,但是用switch寫可讀性會好一些。

如果需要性能的話可以自己手動實現一個跳轉表,現有的動態語言一般都支持一等函數和屬性列表,跳轉表的實現也並不是特別難。

所以其實也就是一個取捨的問題。


最早用vb,剛轉到java時非常不習慣


嚴格來說 應該是整數類型的常量 int char enum都可以的

這是必須是在編譯的時候確定


不一定都是常量,Javascript中,還可以是布爾表達式什麼的


推薦閱讀:

C/C++ 中怎樣優雅的寫多判斷 if 語句?
C語言的宏定義和C++的內聯函數有什麼意義?
C++ 類當中為什麼要有private?
怎麼用好《C++ Primer》(英文版)?
C++11 移動構造函數問題?

TAG:編程語言 | Java | C編程語言 | C | CC |