运算符与表达式

建议先阅读:05_变量与数据类型

原理

表达式求值与副作用

C++ 中,大多数二元运算符不保证左右操作数的求值顺序。i++ + ++i 在同一表达式中对一个变量无序列点的多次修改导致未定义行为。C++17 起部分场景(如 a.b, a->b, a[b], a << b, a >> b)有保证的求值顺序。

短路求值

&&|| 保证从左到右求值且具备短路特性:

  • a && b:a 为 false 时 b 不被求值
  • a || b:a 为 true 时 b 不被求值

编译器利用短路求值进行优化——可将 ptr != nullptr && *ptr > 0 编译为安全的分支代码。

位运算的底层意义

位运算符直接操作 CPU 的位操作指令(AND/OR/XOR/NOT/SHL/SHR),通常单周期完成。常用优化场景:

  • n & 1 判断奇偶
  • n << k 等价于 n * 2
  • n >> k 等价于 n / 2
  • n & (n - 1) 清除最低位的 1,用于判断 2 的幂

整数除法的截断

C++11 规定整数除法向零截断:-7 / 2 = -3(而非 -4)。


语法

运算符分类

类别运算符
算术+ - * / %
自增/自减++(前) ++(后) --(前) --(后)
关系> < >= <= == !=
逻辑&& `
位运算& `
赋值= += -= *= /= %= &= `
三元?:

自增自减

int a = 5;
int b = ++a;  // a=6, b=6 (先加后用)
int c = a++;  // c=6, a=7 (先用后加)

对基本类型无性能差异;对迭代器,++it 优于 it++(后缀需创建临时对象)。

三目运算符

int max = (a > b) ? a : b;
std::cout << (score >= 60 ? "及格" : "不及格") << '\n';

优先级陷阱

优先级陷阱错误写法正确写法
位运算 vs 比较x & 1 == 0(x & 1) == 0
位移 vs 加法a + b << 2(a + b) << 2
逻辑与 vs 逻辑或`a

位运算符 & ^ | 优先级低于比较运算符 == != < >——这是最易出错的陷阱。

位运算常用操作

n & 1           // 判断奇偶: 1=奇 0=偶
n & (n - 1)     // 清除最低位的 1
n & -n          // 获取最低位的 1
x ^= y; y ^= x; x ^= y;  // 交换两数(不能用于同一变量)
 
// 位掩码权限系统
const int READ  = 1 << 0;  // 0001
const int WRITE = 1 << 1;  // 0010
int perm = READ | WRITE;   // 添加权限
perm &= ~WRITE;            // 移除权限
bool canRead = perm & READ; // 检查权限

实践

浮点数比较:

bool approxEqual(double a, double b) {
    return std::abs(a - b) < 1e-9;
}

力扣:
力扣: 简单计算与条件题 (条件+算术)
力扣: 闰年判断题 (逻辑运算符组合)

AI 自检提示:询问 AI “C++ 中位运算符 & 和比较运算符 == 的优先级关系,并举例说明一个常见陷阱”。