一、优先级总表(从高到低)
优先级 | 运算符分类 | 运算符示例 | 结合性 |
---|---|---|---|
1 | 括号与成员访问 | () 、[] 、. 、-> | 左结合 |
2 | 单目运算符 | ++ 、-- 、! 、~ 、* 、& | 右结合 |
3 | 算术运算符(乘除模) | * 、/ 、% | 左结合 |
4 | 算术运算符(加减) | + 、- | 左结合 |
5 | 移位运算符 | << 、>> | 左结合 |
6 | 关系运算符 | < 、<= 、> 、>= | 左结合 |
7 | 相等性判断 | == 、!= | 左结合 |
8 | 按位与 | & | 左结合 |
9 | 按位异或 | ^ | 左结合 |
10 | 按位或 | | | 左结合 |
11 | 逻辑与 | && | 左结合 |
12 | 逻辑或 | || | 左结合 |
13 | 条件运算符 | ?: | 右结合 |
14 | 赋值运算符 | = 、+= 、-= 、<<= 等 | 右结合 |
15 | 逗号运算符 | , | 左结合 |
二、核心原则
- 括号最高:显式使用
()
明确优先级,避免依赖记忆。(a + b) * c; // 强制先计算 a + b
- 单目右结合:前置自增、取地址等从右向左计算。
*ptr++; // 等价于 *(ptr++),而非 (*ptr)++
- 算术 > 移位 > 关系 > 位运算 > 逻辑:
1 << 3 + 1; // 等价于 1 << (3+1) = 16,而非 (1<<3)+1 a < b & c; // 等价于 (a < b) & c,可能逻辑错误!
- 逻辑运算符短路特性:
&&
和||
左侧结果确定后,右侧不执行。if (ptr != NULL && *ptr > 0) // 若 ptr 为 NULL,右侧不执行
三、常见易错点与修正
1. 位运算与逻辑运算混淆
- 错误:
if (a & 0x01 == 0) // 等价于 a & (0x01 == 0) → 永远为假!
- 修正:
if ((a & 0x01) == 0) // 检查最低位是否为0
2. 赋值运算符右结合
- 正确用法:
a = b = 5; // 等价于 a = (b = 5)
3. 条件运算符嵌套
- 右结合特性:
a > b ? a : c > d ? c : d; // 等价于 a > b ? a : (c > d ? c : d)
4. 逗号运算符最低优先级
- 明确分隔:
a = (b=3, c=4, b+c); // a 的值为7
四、实用建议
- 分步简化表达式:
// 复杂表达式: result = (a << 2) + (b & 0xFF) || (c > 10); // 拆解为: int shift_a = a << 2; int mask_b = b & 0xFF; int compare_c = c > 10; result = (shift_a + mask_b) || compare_c;
- 优先使用括号:即使熟悉优先级,显式括号可提升代码可读性。
- 区分
&
和&&
:&
:按位与(所有位参与计算)。&&
:逻辑与(结果非0即1,且短路求值)。
五、速记口诀
括号单目乘除模,加减移位比大小
相等位与异或或,逻辑条件赋值逗。
右结单目三目赋,其余左结莫混淆。