switch
语句 (C++)
允许根据整型表达式的值在多个代码段中进行选择。
语法
selection-statement
:
switch
(
init-statement
optC++17condition
)
statement
init-statement
:
expression-statement
simple-declaration
condition
:
expression
attribute-specifier-seq
optdecl-specifier-seq
declarator
brace-or-equal-initializer
labeled-statement
:
case
constant-expression
:
statement
default
:
statement
备注
switch
语句使控件根据 condition
的值转移到其语句正文中的一个 labeled-statement
。
condition
必须是整数型或明确转换为整数型的类类型。 整型提升按标准转换中所述进行。
switch
语句体由一系列 case
标签和一个 optionaldefault
(可选)标签组成。 A labeled-statement
是其中一个标签和后面的语句。 标记语句不是语法需求,但如果它们不存在,switch
语句是无意义的。 case
语句中没有两个 constant-expression
值可能计算为相同的值。 default
标签只能出现一次。 default
语句通常放在末尾,但它可以出现在 switch
语句正文中的任何位置。 case
或 default
标签只能显示在 switch
语句内部。
每个 case
标签的 constant-expression
都转换为与类型 condition
相同的常量值。 然后,与 condition
比较相等情况。 控件将传递到 case
constant-expression
值后的第一个语句,该语句与 condition
的值匹配。 下表中显示了生成的行为。
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) );
}
在上面的示例中,如果 c
是大写 case'A'
,则 uppercase_A
将递增。 uppercase_A++
之后的 break
语句会终止 switch
语句正文的执行并将控制转移到 while
循环。 如果没有 break
语句,执行将“落入”到下一个标记的语句,以便 lowercase_a
和 other
也会递增。 case 'a'
的 break
语句也能达到类似目的。 如果 c
是小写 case'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++ 未限制 switch
语句中 case
值的数量。 该数量仅受可用内存的限制。
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈