262 lines
25 KiB
HTML
262 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>switch 语句</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_language_switch skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">switch 语句</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>根据条件的值,将控制流转移到若干语句之一。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>switch</b></code> <code><b>(</b></code> <span class="t-spar">初始化语句</span><span class="t-mark">(可选)</span> <span class="t-spar">条件</span> <code><b>)</b></code> <span class="t-spar">语句</span></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">属性</span></td>
|
|
<td>-</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span> 任意数量的<a href="cpp-language-attributes.html">属性</a></td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">初始化语句</span></td>
|
|
<td>-</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span> 下列之一:
|
|
<ul>
|
|
<li>一条<a href="cpp-language-statements.html#.E8.A1.A8.E8.BE.BE.E5.BC.8F.E8.AF.AD.E5.8F.A5">表达式语句</a>(可以是<i>空语句</i>“<code><b>;</b></code>”)</li>
|
|
<li>一条<a href="cpp-language-declarations.html">简单声明</a>,典型地为带初始化器的变量声明,但它可以声明任意多个变量<span class="t-rev-inl t-since-cxx17"><span>或<a href="cpp-language-structured_binding.html">结构化绑定</a></span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span></li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx23">
|
|
<td>
|
|
<ul>
|
|
<li>一条<a href="cpp-language-type_alias.html">别名声明</a></li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx23">(C++23 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<dl>
|
|
<dd>注意任何 <span class="t-spar">初始化语句</span> 必须以分号 <code><b>;</b></code> 结尾,这就是为什么它常被非正式描述为后随分号的表达式或声明。</dd>
|
|
</dl>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">条件</span></td>
|
|
<td>-</td>
|
|
<td>任何整型或枚举类型,或<a href="cpp-language-implicit_conversion.html#.E6.8C.89.E8.AF.AD.E5.A2.83.E8.BD.AC.E6.8D.A2">可按语境隐式转换</a>到整型或枚举类型的类类型的<a href="cpp-language-expressions.html">表达式</a>,或单个这种类型的非数组变量的,带花括号或等号<a href="cpp-language-initialization.html">初始化器</a>的声明。</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">语句</span></td>
|
|
<td>-</td>
|
|
<td>任何<a href="cpp-language-statements.html">语句</a>(典型地为复合语句)。在 <span class="t-spar">语句</span> 中允许使用 <code><b>case:</b></code> 和 <code><b>default:</b></code> 标号,且 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">break</span><span class="sy4">;</span></span></span> 语句具有特殊含义。</td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>case</b></code> <span class="t-spar">常量表达式</span> <code><b>:</b></code> <span class="t-spar">语句</span></td>
|
|
<td>(1)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>default</b></code> <code><b>:</b></code> <span class="t-spar">语句</span></td>
|
|
<td>(2)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">常量表达式</span></td>
|
|
<td>-</td>
|
|
<td>与 <span class="t-spar">条件</span> 经过转换和<a href="cpp-language-implicit_conversion.html#.E6.95.B4.E5.9E.8B.E6.8F.90.E5.8D.87">整型提升</a>后的类型相同的常量表达式</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>switch 语句的体可拥有任意数量的 <code>case:</code> 标号,只要所有 <span class="t-spar">常量表达式</span> 的值(在转换/提升后)均为唯一。最多可以存在一个 <code>default:</code> 标号。(尽管嵌套的 switch 语句可以使用其自身的 <code>default:</code> 标号,或拥有和外部 switch 使用完全相同的常量的 <code>case:</code> 标号)</p>
|
|
<p>如果 <span class="t-spar">条件</span> 求值为等于 <span class="t-spar">常量表达式</span> 之一的值,那么控制被转移到用该 <span class="t-spar">常量表达式</span> 标号标记的语句。</p>
|
|
<p>如果 <span class="t-spar">条件</span> 求值为不匹配任何 <code>case:</code> 标号的值,且存在 <code>default:</code> 标号,那么控制被转移到带有 <code>default:</code> 标号的语句。</p>
|
|
<p>当 <span class="t-spar">语句</span> 中遇到 <a href="cpp-language-break.html">break</a> 语句时退出 switch 语句:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">switch</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span> <span class="sy4">:</span> cout <span class="sy1"><<</span> <span class="st0">'1'</span><span class="sy4">;</span> <span class="co1">// 打印 "1",</span>
|
|
<span class="kw1">case</span> <span class="nu0">2</span> <span class="sy4">:</span> cout <span class="sy1"><<</span> <span class="st0">'2'</span><span class="sy4">;</span> <span class="co1">// 然后打印 "2"</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">switch</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span> <span class="sy4">:</span> cout <span class="sy1"><<</span> <span class="st0">'1'</span><span class="sy4">;</span> <span class="co1">// 打印 "1"</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span> <span class="co1">// 然后退出 switch</span>
|
|
<span class="kw1">case</span> <span class="nu0">2</span> <span class="sy4">:</span> cout <span class="sy1"><<</span> <span class="st0">'2'</span><span class="sy4">;</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>编译器可能在发生直落(抵达下个 case 标号而没有无 break)时发布警告,除非属性 <a href="cpp-language-attributes.html"><code>[[fallthrough]]</code></a> 紧接该标号之前出现以指示该直落是有意的。</p>
|
|
<p>如果使用 <span class="t-spar">初始化语句</span>,那么 switch 语句等价于</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>{</b></code><br />
|
|
<dl>
|
|
<dd><span class="t-spar">初始化语句</span><br /></dd>
|
|
<dd><code><b>switch</b></code> <code><b>(</b></code> <span class="t-spar">条件</span> <code><b>)</b></code> <span class="t-spar">语句</span><br /></dd>
|
|
</dl>
|
|
<p><code><b>}</b></code></p>
|
|
</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>但 <span class="t-spar">初始化语句</span> 所声明的名字(如果 <span class="t-spar">初始化语句</span> 是声明)和 <span class="t-spar">条件</span> 所声明的名字(如果条件是声明)处于同一作用域中,该作用域也是 <span class="t-spar">语句</span> 的作用域。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>因为控制转移时<a href="cpp-language-goto.html">不允许进入变量的作用域</a>,所以如果在 <span class="t-spar">语句</span> 中遇到声明语句,那么它的作用域必须被限制在它自身的复合语句之内:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">switch</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span><span class="sy4">:</span> <span class="kw4">int</span> x <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 初始化</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> x <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">default</span><span class="sy4">:</span> <span class="co1">// 编译错误:跳到 default: 会在尚未初始化 'x' 的情况下进入它的作用域</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"default<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">switch</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span><span class="sy4">:</span> <span class="br0">{</span> <span class="kw4">int</span> x <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> x <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> <span class="co1">// 'x' 的作用域在此结束</span>
|
|
<span class="kw1">default</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"default<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="co1">// 无错误</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.85.B3.E9.94.AE.E8.AF.8D">关键词</span></h3>
|
|
<p><a href="cpp-keyword-switch.html"><tt>switch</tt></a>, <a href="cpp-keyword-case.html"><tt>case</tt></a>, <a href="cpp-keyword-default.html"><tt>default</tt></a></p>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<div class="t-example">
|
|
<p>下列代码展示 <i>switch</i> 语句的几种用法:</p>
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span>
|
|
<span class="kw1">switch</span> <span class="br0">(</span>i<span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"1"</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> <span class="nu0">2</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"2"</span><span class="sy4">;</span> <span class="co1">// 执行从这个标号开始</span>
|
|
<span class="kw1">case</span> <span class="nu0">3</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"3"</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> <span class="nu0">4</span><span class="sy4">:</span>
|
|
<span class="kw1">case</span> <span class="nu0">5</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"45"</span><span class="sy4">;</span>
|
|
<span class="kw1">break</span><span class="sy4">;</span> <span class="co1">// 终止后继语句的执行</span>
|
|
<span class="kw1">case</span> <span class="nu0">6</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"6"</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
|
|
<span class="kw1">switch</span> <span class="br0">(</span>i<span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">4</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"a"</span><span class="sy4">;</span>
|
|
<span class="kw1">default</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"d"</span><span class="sy4">;</span> <span class="co1">// 没有适用的常量表达式</span>
|
|
<span class="co1">// 因此执行 default</span>
|
|
<span class="br0">}</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
|
|
<span class="kw1">switch</span> <span class="br0">(</span>i<span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> <span class="nu0">4</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"a"</span><span class="sy4">;</span> <span class="co1">// 未执行任何语句</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 当在 switch 语句中使用枚举时,如果有一个枚举项没有处理,许多编译器都会发布警告</span>
|
|
<span class="kw2">enum</span> color <span class="br0">{</span>RED, GREEN, BLUE<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">switch</span><span class="br0">(</span>RED<span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">case</span> RED<span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"红<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> GREEN<span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"绿<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> BLUE<span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"蓝<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// C++17 的 初始化语句 语法在不存在到整型或枚举类型的隐式转换时很有用</span>
|
|
<span class="kw1">switch</span> <span class="br0">(</span>Device dev <span class="sy1">=</span> get_device<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> dev.<span class="me1">state</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">case</span> SLEEP<span class="sy4">:</span> <span class="coMULTI">/*...*/</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> READY<span class="sy4">:</span> <span class="coMULTI">/*...*/</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> BAD<span class="sy4">:</span> <span class="coMULTI">/*...*/</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 有问题的示例</span>
|
|
|
|
<span class="co1">// 语句不必是复合语句</span>
|
|
<span class="kw1">switch</span><span class="br0">(</span><span class="nu0">0</span><span class="br0">)</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"什么也不会发生<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 标号也不要求复合语句</span>
|
|
<span class="kw1">switch</span><span class="br0">(</span><span class="kw4">int</span> n <span class="sy1">=</span> <span class="nu0">1</span><span class="br0">)</span>
|
|
<span class="kw1">case</span> <span class="nu0">0</span><span class="sy4">:</span>
|
|
<span class="kw1">case</span> <span class="nu0">1</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> n <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">2345
|
|
d
|
|
红
|
|
1</pre></div>
|
|
</div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td colspan="2"><a href="https://en.wikipedia.org/wiki/Duff%27s_device" class="extiw" title="enwiki:Duff's device">达夫设备</a></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td colspan="2"><a href="https://en.wikipedia.org/wiki/Coroutine#Implementations_for_C" class="extiw" title="enwiki:Coroutine">C/C++ 可以使用达夫设备实现协程</a></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|