根據整數運算式的值,允許在多個程式碼區段中選取範圍。
語法
selection-statement:
switch(init-statementopt C++17condition)statement
init-statement:
expression-statement
simple-declaration
condition:
expression
attribute-specifier-seqoptdecl-specifier-seqdeclaratorbrace-or-equal-initializer
labeled-statement:
caseconstant-expression:statement
default:statement
備註
根據 switch 的值,labeled-statement 陳述式會導致控制項傳輸至在其陳述式本文中的一個 condition。
condition 必須有整數型別,或是具有明確轉換成整數型別的類別型別。 整數升階會如標準轉換中所述來進行。
switch 陳述式正文由一系列 case 標籤和一個可選 default 標籤組成。
labeled-statement 是下列其中一個標籤和後方的陳述式。 有標記的陳述式不是語法需求,但是 switch 陳述式沒有它們就沒有意義。
constant-expression 陳述式中沒有任何兩個 case 值評估為相同的值。
default 標籤只能顯示一次。
default 陳述式通常會放在結尾,但它可以在 switch 陳述式本文中的任何位置出現。
case 或 default 標籤只能出現在 switch 陳述式內。
每個 constant-expression 標籤中的 case 會轉換成與 condition 相同類型的常數值。 然後,它會與 condition 比較是否相等。 控制項會在符合 case 值的 constant-expressioncondition 值之後傳遞至第一個陳述式。 產生的行為如下表所示。
switch 陳述式行為
| 條件 | 動作 |
|---|---|
| 轉換的值與升級之控制運算式的值相符。 | 控制權會轉移至標籤後面的陳述式。 |
沒有常數符合 case 標籤中的常數;default 標籤存在。 |
控制項會傳送至 default 標籤。 |
沒有常數符合 case 標籤中的常數;沒有 default 標籤存在。 |
控制權會轉移至 switch 陳述式之後的陳述式。 |
如果找到相符的表示式,則執行可以繼續進行至稍後的 case 或 default 標籤。
break 陳述式是用來停止執行,並將控制權轉移至 switch 陳述式之後的陳述式。 若沒有 break 陳述式,則會執行相符之 case 標籤到 switch 結尾之間的每一個陳述式,包含 default。 例如:
// switch_statement1.cpp
#include <stdio.h>
int main() {
const char *buffer = "Any character stream";
int uppercase_A, lowercase_a, other;
char c;
uppercase_A = lowercase_a = other = 0;
while ( c = *buffer++ ) // Walks buffer until NULL
{
switch ( c )
{
case 'A':
uppercase_A++;
break;
case 'a':
lowercase_a++;
break;
default:
other++;
}
}
printf_s( "\nUppercase A: %d\nLowercase a: %d\nTotal: %d\n",
uppercase_A, lowercase_a, (uppercase_A + lowercase_a + other) );
}
在上述範例中,如果 uppercase_A 是大寫 c,則遞增 'A'。 在 break 之後的 uppercase_A++ 陳述式會結束 switch 陳述式本文的執行,並將控制權傳遞給 while 迴圈。 如果沒有 break 陳述式,則執行會「繼續執行」到下一個加上標籤的陳述式,如此一來 lowercase_a 和 other 也會遞增。
break 的 case 'a' 陳述式也提供類似的用途。 如果 c 是小寫字母 'a',lowercase_a 則為遞增,並且 break 陳述式將終止 switch 陳述式正文。 如果 c 不是 'a' 或 'A',就會執行 default 陳述式。
Visual Studio 2017 和更新版本 (適用於 /std:c++17 模式和更新版本):[[fallthrough]] 屬性是在 C++17 標準中指定。 您可以在 switch 陳述式中使用它。 這是編譯器或任何讀取程式碼人員的提示,而繼續執行的行為是刻意的。 Microsoft C++ 編譯器目前不會針對繼續執行發出警告,因此這個屬性不會影響編譯器行為。 在此範例中,屬性會套用至未結束標籤陳述式內的空白陳述式。 換句話說,需要分號。
int main()
{
int n = 5;
switch (n)
{
case 1:
a();
break;
case 2:
b();
d();
[[fallthrough]]; // I meant to do this!
case 3:
c();
break;
default:
d();
break;
}
return 0;
}
Visual Studio 2017 15.3 版和更新版本 (適用於 /std:c++17 模式和更新版本):switch 陳述式可能有一個 init-statement 子句,其結尾為分號。 它引進並初始化變數,其範圍僅限於 switch 陳述式的區塊:
switch (Gadget gadget(args); auto s = gadget.get_status())
{
case status::good:
gadget.zip();
break;
case status::bad:
throw BadGadget();
}
只要初始化是可執行到的switch,也就是所有可能的執行路徑都不略過, 陳述式的內部區塊可以包含具有初始設定式的定義。 使用這些宣告引入的名稱有區域範圍。 例如:
// switch_statement2.cpp
// C2360 expected
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
switch( tolower( *argv[1] ) )
{
// Error. Unreachable declaration.
char szChEntered[] = "Character entered was: ";
case 'a' :
{
// Declaration of szChEntered OK. Local scope.
char szChEntered[] = "Character entered was: ";
cout << szChEntered << "a\n";
}
break;
case 'b' :
// Value of szChEntered undefined.
cout << szChEntered << "b\n";
break;
default:
// Value of szChEntered undefined.
cout << szChEntered << "neither a nor b\n";
break;
}
}
switch 陳述式可以是巢狀結構。 巢狀化時,case 或 default 標籤會與括住它們的最接近 switch 陳述式產生關聯。
Microsoft 特定行為
Microsoft C++ 不會限制 case 陳述式中 switch 值的數量。 此數目會受到可用記憶體的限制。