第六章:分支语句和逻辑运算符 | C++ Primer Plus 重点带看

条件运算符的错误防范

为什么有人写 if (3 == x) 而不是 if (x == 3)?

这是一种防御性编程技巧,叫做 Yoda 条件表达式(Yoda Condition),目的是让编译器帮你发现将 == 误写成 = 的错误。

int x = 5;
// 正常写法
if (x = 3) { }     // ❌ 把 3 赋给 x,然后判断 x(=3,非零为真),不会报错,但逻辑错误
// Yoda 写法
if (3 = x) { }     // ✅ 编译报错!不能对字面量 3 赋值

这个技巧来自 C 语言时代,现代 C++ 中不太需要了,因为:

  • 编译器会发警告:大多数编译器对 if (x = 3) 会发出警告(-Wall)。
  • 建议开编译器警告:用 -Wall -Wextra 甚至 -Werror(警告视为错误)。
  • 可读性差:if (3 == x) 读起来不自然。

C++ 中的关系表达式链式写法问题

为什么 if (1 < x < 6) 不是判断 x 是否在 1 到 6 之间:因为 C++ 中 < 运算符是从左到右计算的,1 < x < 6 实际上是 (1 < x) < 6,而不是数学上的 1 < x 且 x < 6。

int x = 10;

// 数学含义:x 是否在 (1, 6) 之间? → 否,10 不在
// C++ 实际执行:

// 第一步:1 < x → 1 < 10 → true → 转为 int 得 1
// 第二步:1 < 6 → true

if (1 < x < 6) { }    // x = 10 时居然为 true!
// 误以为 a == b == c 表示三者相等
int a = 1, b = 1, c = 0;
if (a == b == c) { }     // (a == b) == c → (1 == 1) == 0 → 1 == 0 → false
                          // ❌ 不是 a==b 且 b==c
// 正确写法
if (a == b && b == c) { }

// 误以为 a != b != c 表示三者互不相等
if (a != b != c) { }     // (a != b) != c → (false) != 0 → true
                          // ❌ 语义完全错误
// 正确写法
if (a != b && b != c && a != c) { }

唯一需要三操作数的运算符:条件运算符 ?:

int max = (a > b) ? a : b;   // 条件 ? 真值 : 假值
// 三个操作数:
//      条件:a > b
//      真值:a
//      假值:b

switch 语句注意事项

1、括号里面必须是一个结果为整形的表达式不能进行浮点测试;原因:switch 的底层实现是跳转表(jump table),编译器需要用表达式的值作为索引直接跳转。浮点数精度问题、字符串无法直接做索引,所以都不允许。

int x = 2;
switch (x) { }              // ✅ int

char ch = 'a';
switch (ch) { }             // ✅ char 本质上是整型

enum Color { RED, GREEN, BLUE };
switch (RED) { }            // ✅ 枚举值本质上是整型

bool flag = true;
switch (flag) { }           // ✅ bool 本质上是整型

double d = 1.5;
switch (d) { }              // ❌ 编译报错,浮点型不允许

float f = 1.0f;
switch (f) { }              // ❌ 编译报错

std::string s = "hello";
switch (s) { }              // ❌ 编译报错,非整型

2、case 标签必须是整型常量表达式。

int x = 2;

switch (x) {
    case 1: break;                      // ✅ 整数字面量
    case 'a': break;                    // ✅ 字符常量,本质是 int(97)
    case RED: break;                    // ✅ 枚举值,本质是 int

    const int N = 3;
    case N: break;                      // ✅ const 整型变量,编译期可知

    constexpr int M = 4;
    case M: break;                      // ✅ constexpr,编译期可知

    int y = 5;
    case y: break;                      // ❌ 编译报错,y 不是常量表达式

    case 3.14: break;                   // ❌ 浮点常量
    case "hello": break;                // ❌ 字符串常量

    int a = 1;
    case a + 1: break;                  // ❌ a 不是常量
}
C++ Primer Plus 文章被收录于专栏

C++ Primer Plus 精读|从入门到面试,重点内容全程带看。 本专栏以《C++ Primer Plus》为蓝本,逐章提炼必考知识点、易错点、面试高频考点,跳过冗余示例,直击语法本质与工程实践,帮你高效吃透 C++ 基础,夯实底层开发必备能力。

全部评论
欢迎订阅专栏《C++/嵌入式开发 秋招面经》:https://www.nowcoder.com/creation/manager/columnDetail/MKaoll
点赞 回复 分享
发布于 昨天 18:15 河北

相关推荐

肥肠椒绿:双非本可不就犯天条了,双非本就应该打入无间地狱
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务