运算符与表达式

建议先阅读: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 (先用后加)
```cpp
 
对基本类型无性能差异;对迭代器,`++it` 优于 `it++`(后缀需创建临时对象)。
 
### 三目运算符
 
```cpp
int max = (a > b) ? a : b;
std::cout << (score >= 60 ? "及格" : "不及格") << '\n';
```cpp
 
### 优先级陷阱
 
| 优先级陷阱 | 错误写法 | 正确写法 |
|-----------|----------|---------|
| 位运算 vs 比较 | `x & 1 == 0` | `(x & 1) == 0` |
| 位移 vs 加法 | `a + b << 2` | `(a + b) << 2` |
| 逻辑与 vs 逻辑或 | `a || b && c` | 加括号明确意图 |
 
> 位运算符 `& ^ |` 优先级**低于**比较运算符 `== != < >`——这是最易出错的陷阱。
 
### 位运算常用操作
 
```cpp
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; // 检查权限
```asm
 
---
 
## 实践
 
浮点数比较:
```cpp
bool approxEqual(double a, double b) {
 return std::abs(a - b) < 1e-9;
}
```cpp
 
练习:
练习: 简单计算与条件题 (条件+算术)
练习: 闰年判断题 (逻辑运算符组合)