【C/C++】 switch-case 详解/全面总结

简介: 关于 C语言/C++ 中,switch-case 的尽量详细和全面的解释与总结

I - 基础概述


类似 if-else 语句,switch-case 语句用于处理复杂的条件判断和分支操作,但相较前者有更好的可读性,在代码中出现冗长的 if-else 阶梯代码时,switch-case 语句可作为一个不错的替代方案。

1.1 - 基础结构


一个 switch 语句可以包含任意数量的 case 标签,每个 case 标签中可执行若干条语句,通常以 break 语句结束。default 标签为可选项,至多包含一个,用于处理 case 标签未列举的值。

switch (expression)
{
   
    case constant_expression_1 :
        // statement_1
        break;
    case constant_expression_2 :
        // statement_2
        break;
        /* ... */

    default:
        // statement_default
        break;
}

switch 语句根据 expression (表达式) 的值,跳转到值对应的 case 标签,执行标签中包含的语句或语句块。

1.2 - 使用举例


#include <iostream>
int main(int argc, char* argv[])
{
   
    const int x = 2;
    switch (x)
    {
   
        case 1: 
            std::cout << "x equals 1" << std::endl;
            break;
        case 2: 
            std::cout << "x equals 2" << std::endl;
            break;
        case 3: 
            std::cout << "x equals 3" << std::endl;
            break;
        default:
            std::cout << "x is other than 1, 2 and 3" << std::endl;
            break;
    }
    return 0;
}

输出:

x equals 2

switch 根据 x 的值,跳转到匹配的 case ,执行其中的语句,此处为 2 ,遇到 break 结束。

II - 注意事项

2.1 - switch 语句中的表达式必须为整型


switch 语句中使用的表达式必须是整型 (int, char, enum) 表达式,不允许为其他类型。

// float type is not allowed in switch expression
float x = 1.1;
switch (x)
{
   
    case 1.1: printf("case 1.1"); break;
    default: printf("default"); break;
}

MSVC 编译器的报错为:

error C2450: switch expression of type 'float' is illegal
note: Integral expression required

switch 表达式类型 float 非法,要求整型表达式。

Java 中的 switch-case 语句中允许字符串类型。

2.2 - 满足条件的 case 标签后的语句都会执行,直到 break 语句


表达式值对应的 case 标签后的语句都会执行,直到遇到 break 语句,或者 switch 结束。标签结尾如果没有使用 break 则会 fall-through ("穿透")。

示例:

const int x = 2;
switch (x)
{
   
    case 1: std::cout << "x equals 1" << std::endl;
    case 2: std::cout << "x equals 2" << std::endl;
    case 3: std::cout << "x equals 3" << std::endl;
    [[fallthrough]];
    default : std::cout << "x is other than 1, 2 and 3" << std::endl;break;
}

输出:

x equals 2
x equals 3
x is other than 1, 2 and 3

注:[[fallthrough]] 为 C++17 引入的属性,用于禁止编译器产生 fall-through 的 "穿透" 警告。

2.3 - default 标签可以置于任何位置


default 标签可以置于 switch 内的任何位置,无论位置先后,如果没有任何的 case 值匹配,则会执行 default 标签后的语句。

int x = 4;
switch (x)
{
   
    default : std::cout << "x is other than 1, 2 and 3" << std::endl;break;
    case 1: std::cout << "x equals 1" << std::endl; break;
    case 2: std::cout << "x equals 2" << std::endl; break;
}

输出

 x is other than 1, 2 and 3

结合前一小节,default 标签中无 break 语句,也会穿透,直到 break 为止,示例:

int x = 4;
switch (x)
{
   
    default : std::cout << "x is other than 1, 2 and 3" << std::endl;
    case 1: std::cout << "x equals 1" << std::endl;break;
    case 2: std::cout << "x equals 2" << std::endl;
}

此处打印为:

x is other than 1, 2 and 3
x equals 1

由于 case 1 包含 break 语句,只“穿透”到 case 1。

2.4 - 标签使用的整型表达式必须为常量


case 标签使用的整型表达式必须是常量表达式。

// A program with variable expressions in labels
#include <stdio.h>
int main()
{
   
    int x = 2;
    int arr[] = {
   1, 2, 3};
    switch (x)
    {
   
        case arr[0]: printf("Choice 1\n");
        case arr[1]: printf("Choice 2\n");
        case arr[2]: printf("Choice 3\n");
    }
    return 0;
}

编译报错为:

error C2131: expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of 'arr'
error C2051: case expression not constant

case 表达式不为常量

2.5 - case 之前的语句永远不会执行


在 switch 语句后,控制语句跳转到匹配的 case 标签,写在 case 标签前的语句不会被执行。

示例:

// statement before all cases are never executed
int x = 2;
switch (x)
{
   
    x = x + 1; // 此条语句不会执行, this statement is not executed
    case 1: std::cout << "x equals 1" << std::endl; break;
    case 2: std::cout << "x equals 2" << std::endl; break;
    case 3: std::cout << "x equals 3" << std::endl; break;
    default : std::cout << "x is other than 1, 2 and 3" << std::endl;break;
}

此时输出为

x equals 2

而不是 x equals 3 ,由于语句 x = x + 1 不会执行。

2.6 - case 标签不可以使用重复的值


// duplicate case value
int x = 2;
switch (x)
{
   
    case 1+1: std::cout << "x equals 1" << std::endl; break;
    case 2: std::cout << "x equals 2" << std::endl; break;
    case 3: std::cout << "x equals 3" << std::endl; break;
    default : std::cout << "x is other than 1, 2 and 3" << std::endl;break;
}

编译报错为:

error C2196: case value '2' already used

case 标签值 '2' 已使用。

III - 特殊用法

3.1 - case 设置范围


可在单个 case 标签指定一个连续的数值范围,低值在前,高值在后。

case low ... high:

... 左右两边需要有一个空格

case 1 ... 5: // correct
case 1...5: // wrong

除可以使用整数外,还可以使用如字符型常量。

case 'A' ... 'Z':

使用举例:

#include <stdio.h>

int main(int argc, char* argv[]) 
{
   
   int data[10] = {
    5, 4, 10, 25, 60, 47, 23, 80, 14, 11};
   int i;
   for (i = 0; i < 10; ++i)
   {
   
      switch (data[i])
      {
   
         case 1 ... 10:
            printf("%d 在范围 1 - 10 之间\n", data[i]);
         break;
         case 11 ... 20:
            printf("%d 在范围 11 - 20 之间\n", data[i]);
         break;
         case 21 ... 30:
            printf("%d 在范围 21 - 30 之间\n", data[i]);
         break;
         case 31 ... 40:
            printf("%d 在范围 31 - 40 之间\n", data[i]);
         break;
         default:
            printf("%d 超出范围\n", data[i]);
         break;
      }
   }
}

输出

5 在范围 1 - 10 之间
4 在范围 1 - 10 之间
10 在范围 1 - 10 之间
25 在范围 21 - 30 之间
60 超出范围
47 超出范围
23 在范围  21 - 30 之间
80 超出范围
14 在范围 11 - 20 之间
11 在范围 11 - 20 之间

查看 gcc 官网的描述 :
https://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC82

注:

  • 仅 GCC 支持, Visual Studio 的 MSVC 编译器当前不支持。

3.2 - switch 初始化语句


C++17 标准引入新特性,switch 语句中允许初始化语句。

switch (init-statement; expression)
{
   
    case constant_expression: 
        statement; 
        break;
    /* ... */
}
// 等价于
{
   
    init-statement;
    switch (expression)
    {
   
        case constant_expression: 
        statement; 
        break;
        /* ... */
    }
}

使用示例:

struct RemoteDevice
{
   
    enum State {
    SLEEP, READY, ERROR };
    auto state() const {
    return m_state; }

    /*...*/

private:
    State m_state{
   };
};

switch (auto rmt = RemoteDevice{
   }; rmt.state())
{
   
case RemoteDevice::SLEEP:
    /*...*/
    break;
case RemoteDevice::READY:
    /*...*/
    break;
case RemoteDevice::ERROR:
    /*...*/
    break;
}

3.3 - switch-case 符合语法的简易结构


switch 语句可以不为完整的复合结构,示例:

// 此条不做任何事
switch (0)
    std::cout << "this doses nothing\n";


switch (int n = 1)
{
   
    case 0:
    case 1:
        std::cout << n << '\n';
}

同 if / while 等语句,switch 语句无大括号时,可紧跟一个标签以及一条语句。

// 此条总是打印
switch (0)
    default:
        std::cout << "this print always\n";

IV - 与 if else if 的比较


switch if else if
执行不同的 case 基于 switch 中的变量值 执行不同的代码块,基于指定的条件判断
仅可执行整型表达式 (int, char, enum) 可执行任意类型的表达式
在较多的条件判断时,更快且具有更好的可读性 当有很多条件时,它会变得混乱。
不支持逻辑表达式判断 可支持逻辑表达式,以及范围的判断
  • 编译不同:

当编译器编译 switch 语句时,它将检查每个 case 常量并创建一个“跳转表”,该表将用于根据表达式的值选择执行路径。因此,如果我们需要在一大组值中进行选择,switch 语句的运行速度将比使用 if-else 序列编码的等效逻辑快得多。编译器可以这样做,因为它知道 case 常量都是相同的类型,并且必须与 switch 表达式进行比较以相等,而在 if 表达式的情况下,编译器没有这样的认知。

  • 速度基于条件数量:

switch 语句比 if else if 更快的前提是条件足够多。如果只有少数判断,则可能不会影响速度。如过条件数超过 5 个,则首选 switch-case ,否则也可以使用 if-else。

如果 switch 包含五个以上的条件,则使用查找表 (lookup table) 或哈希链 (hash list) 实现。这意味着所有条件获得相同的访问时间,而在 if else if 列表中,最后一个条件需要更多时间才能到达,因为它必须首先评估之前的每个条件。

V - 参考链接

目录
相关文章
|
网络协议 API
端口复用(bind error: Address already in use 问题)
端口复用(bind error: Address already in use 问题)
1685 0
micropython esp8266+ssd1306(OLED) 显示中文(示例)
1.Adafruit_SSD1306 OLED显示库使用Adafruit_SSD1306:https://github.com/adafruit/Adafruit_SSD1306 连接示例: 库使用示例: >>> from ...
8065 0
|
10月前
|
SQL 数据可视化 大数据
我是谁?我从哪来?我要到哪去?——聊聊数据血缘分析的“前世今生”
我是谁?我从哪来?我要到哪去?——聊聊数据血缘分析的“前世今生”
697 11
|
8月前
|
编译器 开发工具 C语言
【2026最新】VSCode下载、安装和使用保姆级教程(附安装包+图文步骤)
Visual Studio Code(VSCode)是微软开发的免费开源跨平台代码编辑器,轻量高效,支持50多种编程语言。通过丰富插件可扩展功能,兼具简洁与强大,广泛应用于Web开发、数据科学等领域,是全球开发者首选工具之一。
18259 7
|
12月前
|
存储 JSON 对象存储
零门槛玩转向量引擎!阿里云 Milvus 无代码全流程实操指南
阿里云Milvus版是企业级向量引擎,支持非结构化数据语义检索。全托管架构、开源兼容,助力智能驾驶、电商推荐、智能客服等场景实现毫秒级精准匹配,无代码操作让AI落地更高效。
1495 0
|
前端开发 NoSQL 关系型数据库
如何开发研发项目管理中的需求管理板块?(附架构图+流程图+代码参考)
本文探讨了中小企业在研发或产品工作中常见的需求管理问题,如需求记录混乱、交付靠口头约定、变更无追踪等。通过系统化的需求管理,可实现“谁在做什么、为什么做、何时完成、谁验收”的可视化与责任归属,减少沟通成本,提升效率。文章详细介绍了需求管理的核心功能模块(如需求看板、处理流程、研发日报)、系统架构设计、前后端实现参考、开发技巧与落地建议,以及上线后的运营指标与实施路线图。最终目标是将松散的流程规范化、可追踪、可复用,助力企业构建高效的研发项目管理体系。
|
人工智能 算法 物联网
ComfyUI:搭积木一样构建专属于自己的AIGC工作流(保姆级教程)
通过本篇文章,你可以了解并实践通过【ComfyUI】构建自己的【文生图】和【文生动图】工作流。
25570 5
ComfyUI:搭积木一样构建专属于自己的AIGC工作流(保姆级教程)
|
C语言 C++
C语言9🔥:switch case 语句
C语言9🔥:switch case 语句
2439 0