火龙信奥
  • 分享
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

C++ 分支控制结构:`if` 与 `switch` 完全讲义

作者: 作者的头像   huolong , 时间:2026-08-24 15:46:02 , 所有人可见, 阅读  45

C++ 分支控制结构:if 与 switch 完全讲义

分支结构允许程序根据不同的条件执行不同的代码路径。掌握分支控制是编写复杂算法与业务逻辑的第一步。


目录

  1. 前置知识回顾:逻辑与关系运算符
  2. 一、if 家族分支控制
  3. 1. 单分支 if
  4. 2. 双分支 if - else
  5. 3. 多分支 if - else if - else
  6. 4. 嵌套分支与“悬空 else”陷阱
  7. 二、switch - case 多值匹配分支
  8. 1. 基本语法与执行流程
  9. 2. 关键机制:break 与“穿透现象”
  10. 3. default 关键字的深入解析
  11. 4. switch 的类型限制与作用域陷阱
  12. 三、if-else 与 switch-case 核心对比与选型
  13. 四、初学者高频踩坑总结

前置知识回顾

分支语句的判断条件依赖 关系运算 与 逻辑运算 的组合,其计算结果为布尔值(true 或 false):

1. 关系运算符(比较大小)

运算符 含义 示例 结果
== 等于(注意是双等号) 5 == 5 true
!= 不等于 5 != 3 true
>, < 大于、小于 3 < 5 true
>=, <= 大于等于、小于等于 5 >= 5 true

2. 逻辑运算符(复合条件连接)

运算符 含义 逻辑规则 示例
&& 逻辑与 (AND) 两边都为真,结果才为真 (x > 0) && (x < 10)
\|\| 逻辑或 (OR) 只要一边为真,结果就为真 (x == 1) \|\| (x == 2)
! 逻辑非 (NOT) 取反(真变假,假变真) !(x == 0) 等价于 x != 0

⚡ 短路求值特性(Short-circuit Evaluation): - A && B:如果 A 为 false,则 不会执行 B(因为整体必为假)。 - A || B:如果 A 为 true,则 不会执行 B(因为整体必为真)。

利用短路可以写出安全的防越界代码:if (idx < arr.size() && arr[idx] == target)。


一、if 家族分支控制

1. 单分支 if

当条件成立(值为 true 或非 0)时,执行指定代码块;否则直接跳过。

       [ 判断条件 ]
        /        \
 (true)/          \(false)
      v            \
[ 执行语句块 ]      |
      \            /
       v          v
     [ 继续向下执行 ]
#include <iostream>

int main() {
    int score = 85;

    // 单分支 if
    if (score >= 60) {
        std::cout << "成绩及格!" << std::endl;
    }

    // 注意:如果语句块只有单行,大括号可以省略,但强烈建议永远加上大括号!
    return 0;
}

2. 双分支 if - else

实现“非此即彼”的二选一逻辑。

#include <iostream>

int main() {
    int n = 7;

    if (n % 2 == 0) {
        std::cout << n << " 是偶数。" << std::endl;
    } else {
        std::cout << n << " 是奇数。" << std::endl;
    }

    return 0;
}

3. 多分支 if - else if - else

处理“多选一”的排他性条件。程序自上而下逐个检查条件,一旦某个条件成立,执行其代码块后立即跳出整个 if-else 结构,后续分支不再进行判断。

#include <iostream>

int main() {
    int score = 82;

    if (score >= 90) {
        std::cout << "优秀 (A)" << std::endl;
    } else if (score >= 80) {
        // 走到这里隐含了 score < 90 的条件
        std::cout << "良好 (B)" << std::endl;
    } else if (score >= 60) {
        // 走到这里隐含了 score < 80 的条件
        std::cout << "及格 (C)" << std::endl;
    } else {
        // 上述条件全部不成立时执行
        std::cout << "不及格 (D)" << std::endl;
    }

    return 0;
}

4. 嵌套分支与“悬空 else”陷阱

if 语句内部可以再嵌套 if 或 if-else。

⚠️ 悬空 else 规则(Dangling Else): 在 C++ 中,else 永远与前面最近的未匹配的 if 配对,与代码缩进无关!

#include <iostream>

int main() {
    int x = 5, y = 15;

    // ❌ 错误示范:错误的缩进会产生视觉欺骗
    if (x > 10)
        if (y > 10)
            std::cout << "x > 10 且 y > 10" << std::endl;
    else
        std::cout << "x <= 10 ??? (其实这里是 y <= 10 !)" << std::endl;

    // ✅ 正确示范:显式加上花括号明确作用域
    if (x > 10) {
        if (y > 10) {
            std::cout << "x > 10 且 y > 10" << std::endl;
        }
    } else {
        std::cout << "x <= 10" << std::endl;
    }

    return 0;
}

二、switch - case 多值匹配分支

switch 语句是专为等值多路分支设计的控制结构。相比长串的 if - else if,它在离散值匹配时更清晰、更高效。

1. 基本语法与执行流程

switch (表达式) {
    case 常量值1:
        // 执行语句1
        break;
    case 常量值2:
        // 执行语句2
        break;
    // ... 可以有任意个 case
    default:
        // 所有 case 都不匹配时执行
        break;
}

2. 关键机制:break 与穿透现象(Fall-through)

switch 匹配到某个 case 之后,会从该 case 开始向下顺序执行代码,直到遇到 break 才会跳出 switch。

如果遗漏了 break,程序会无视后面的 case 判定条件,直接“穿透”并执行后续 case 中的代码!

示例:利用穿透实现多条件归并

穿透并非只有害处,有时可以巧妙利用(如多个值执行相同逻辑):

#include <iostream>

int main() {
    int month = 4;

    switch (month) {
        case 12:
        case 1:
        case 2:
            std::cout << "冬季" << std::endl;
            break; // 跳出 switch
        case 3:
        case 4:
        case 5: // month = 4 会命中并穿透到这里
            std::cout << "春季" << std::endl;
            break;
        case 6:
        case 7:
        case 8:
            std::cout << "夏季" << std::endl;
            break;
        case 9:
        case 10:
        case 11:
            std::cout << "秋季" << std::endl;
            break;
        default:
            std::cout << "无效的月份!" << std::endl;
            break;
    }

    return 0;
}

3. default 关键字的深入解析

  • 作用:当表达式的值与所有 case 的常量值都不匹配时,程序将跳转到 default 分支执行。
  • 位置:default 通常写在最后,但语法上允许放在任意位置(开头、中间、结尾均可)。
  • 执行顺序:无论 default 处于代码的哪个位置,它始终是在所有 case 都不匹配后才会被执行。如果 default 不在末尾且没有加 break,它同样会向后“穿透”执行后续的 case!
  • 可省略性:default 是可选的。如果省略且没有匹配的 case,则整个 switch 什么都不做。
#include <iostream>

int main() {
    int code = 99;

    switch (code) {
        case 1:
            std::cout << "操作成功\n";
            break;
        case 2:
            std::cout << "操作等待\n";
            break;
        default: // 处理所有未知/异常情况,增强程序健壮性
            std::cout << "未知错误码: " << code << "\n";
            break;
    }
    return 0;
}

4. switch 的类型限制与作用域陷阱

① 限制:表达式必须是【整数类型】或【枚举】

  • 支持:int, char, short, long, long long, enum, bool(本质是整型)。
  • 不支持:float, double(浮点数无法精准哈希匹配)、std::string 等对象。

② 限制:case 后面必须是【编译期常量】

int x = 5;
const int TARGET = 10;
int dynamicVal = 20;

switch (x) {
    case 5:          // ✅ 合法:字面量
    case TARGET:     // ✅ 合法:编译期 const 常量
    // case dynamicVal: // ❌ 编译报错:非常量表达式
    // case 1 ... 5:    // ❌ C++ 标准不支持此区间语法(除部分 GCC 扩展)
        break;
}

③ 陷阱:在 case 内定义初始化变量需要加 {}

在 case 内部如果定义带初始化的变量,必须用花括号 {} 限制其局部作用域,否则编译器会报错(防止跳过变量初始化的跨标签跳转):

switch (x) {
    case 1: {
        // ✅ 使用大括号圈定作用域
        int a = 100;
        std::cout << a << std::endl;
        break;
    }
    case 2:
        // int b = 200; // ❌ 编译报错:跨跳初始化
        break;
}

三、if-else 与 switch-case 核心对比与选型

比较维度 if - else if - else switch - case
条件类型 任意逻辑表达式(区间、复合条件) 仅限离散的整型/字符常量
支持数据类型 整型、浮点型、字符串、自定义对象等 仅限整型、字符型、枚举
匹配方式 顺序自上而下逐条计算判定($O(N)$) 通常由编译器生成跳转表(Jump Table),近似 $O(1)$ 查找
可读性 适合复杂的组合判断、范围判断 适合枚举状态机、菜单命令分发

选型口诀:

  1. 范围区间判定(如 0 <= x && x <= 100)$\rightarrow$ 选 if-else。
  2. 复合条件判断(如 a > 0 && b < 5 || flag)$\rightarrow$ 选 if-else。
  3. 浮点数 / 字符串判定 $\rightarrow$ 选 if-else。
  4. 单变量的离散固定值匹配(如按键检测、命令码、状态机)$\rightarrow$ 优先选 switch-case。

四、初学者高频踩坑总结

坑点 1:把判等 == 误写成赋值 =

int flag = 0;
// ❌ 错误:flag = 1 变成了赋值语句,且表达式结果恒为 1 (true)
if (flag = 1) { 
    std::cout << "永远会执行!" << std::endl;
}

// ✅ 正确:使用 ==
if (flag == 1) { ... }

// 💡 技巧(Yoda 条件写法,防手误):
if (1 == flag) { ... } // 如果写成 1 = flag,编译器会直接报错拦截

坑点 2:数学连等式误区

int x = 15;
// ❌ 错误:数学中的 0 < x < 10 在 C++ 中会先算 (0 < 15) 得 true(1),再算 1 < 10 得 true(1)!
if (0 < x < 10) { 
    std::cout << "错误触发!" << std::endl;
}

// ✅ 正确:使用逻辑与 && 显式连接两个关系表达式
if (x > 0 && x < 10) {
    std::cout << "只有在 0 到 10 之间才会执行" << std::endl;
}

坑点 3:if 后面手滑加分号 ;

int a = 3;
// ❌ 致命错误:分号直接结束了 if 语句,导致下面的大括号无条件执行!
if (a > 5); 
{
    std::cout << "a 其实小于 5,但这里依然输出了!" << std::endl;
}

坑点 4:switch 中漏写 break

忘记写 break 导致的“穿透”是 C/C++ 中最常见、排查成本最高的隐蔽 Bug 之一。除非刻意利用穿透合并逻辑,否则务必在每个 case 以及 default 结尾显式书写 break;。

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

关于火龙

  • 关于我们
  • 学员获奖
  • 预约试听
  • ACM课程
  • CSP课程
  • 学习指南

帮助中心

  • 用户协议
  • 打字练习
  • 在线画图
  • DevC++下载
  • CSP报名
  • GESP官网

推荐课程

  • C++零基础入门(可试看)
  • C++进阶提升
  • GESP考级辅导
  • GESP打卡
  • CSP-J/S打卡

公众号

火龙信奥公众号二维码

地址:义乌市北门街188号新天地商厦二楼2F 邮箱:wdlok305@126.com

© 2017-2026 义乌市睿码科技有限公司版权所有 浙ICP备2021013995号

火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码