运算符与表达式
建议先阅读: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 * 2n >> k等价于 n / 2n & (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
练习:
练习: 简单计算与条件题 (条件+算术)
练习: 闰年判断题 (逻辑运算符组合)