📄 一句话概括
一行代码里有好几个运算符时,谁先算由两个规则决定:优先级(分高先算)和结合性(同级时从哪头开始)。本节给你一张金字塔 + 两句口诀——但真正的铁律只有一条:记不清就加括号。
一、优先级:分高先算
前面小节其实一直在用优先级(只是没点破):
int x = 3 + 4 * 2; // * 高于 + → 3+8=11,不是 14
bool r = 5 > 3 && 2 < 1; // 关系高于逻辑 → (5>3) && (2<1) = 1 && 0 = 0
int y = a << 2 + 1; // + 高于 << → a << 3(3.1.6 的坑)
cout << 5 > 3; // << 高于 > → (cout<<5) > 3(3.1.2 的坑)
金字塔主分层(从高到低):
() 括号 · 一元 ! ~ ++ --
* / % ← 算术二楼
+ - ← 算术一楼
<< >>
> < >= <= ← 关系
== != ← 比 > < 再低一层!
&&
||
? : 与赋值 = += (很低)
, (垫底)
两句高频口诀:
- 算术 > 移位 > 关系 > 逻辑 > 赋值 > 逗号——大方向先抓这条
- 细节层的雷:
==!=比<>低(a < b == c是(a<b)==c);&&比||高;<<比+低、比关系高
二、结合性:同级分不出胜负,看方向
两个运算符同优先级时,按结合性决定从哪头开始:
| 结合性 | 方向 | 代表运算符 |
|---|---|---|
| 左结合 | 从左往右 | 算术、关系、逻辑、移位、逗号 |
| 右结合 | 从右往左 | 赋值 = 复合赋值、条件 ? :、一元 ! |
// 左结合:100 / 5 / 2 从左往右 = (100/5)/2 = 10
// 若从右往左就成 100/(5/2)=50——差远了
cout << 100 / 5 / 2 << endl; // 10
// 右结合:a = b = 0 从右往左 = a = (b = 0)(3.1.4 连等号的原理)
减法除法不能换序、赋值连等从右往左——这两个场景覆盖了 90% 的结合性考点。
三、铁律:记不清就加括号
优先级表有 50 多行,没有人背全表——资深程序员的武器就是括号:
// 别人能看懂的写法
if ((a > b) && (c < d) || (e == f))
// 编译器能猜、人看懵的写法
if (a > b && c < d || e == f)
两个式子机器执行完全一样,但第一个人和三个月后的你自己都读得懂。规则:
- 不同分层的运算符混用 → 加括号(
<<与比较、关系与逻辑混用必加) - 三目、逗号、移位参与复杂式子 → 整体套括号(前面三节的现场教训)
- 拿不准 → 上括号,零成本买保险
括号不改变正确答案,只改变出错概率和可读性。编译器不在乎多几对括号,你的同事和你未来的自己在乎。
四、动手 Demo:人肉编译器
先在纸上算出每个式子的值,再跑程序对答案:
#include <iostream>
using namespace std;
int main() {
cout << 3 + 4 * 2 << endl; // 11(* 先算)
cout << 100 / 5 / 2 << endl; // 10(左结合)
cout << 5 > 3 << endl; // 报错或怪结果:<< 优先级高于 >(演示坑)
cout << (5 > 3) << endl; // 1:加括号救回来
cout << (3 + 4 > 5 && 2 + 1 > 2) << endl; // (7>5)&&(3>2)=1&&1=1
int a = 1, b = 2, c = 3;
a = b = c; // 右结合:三个都变 3
cout << a << b << c << endl; // 333
cout << (a << 2 + 1) << endl; // 3<<3=24(+ 高于 <<)
return 0;
}
看到什么算成功:11 10 1 1 333 24(cout << 5 > 3 那行按编译器不同可能直接编译不过——这正是教材想让你看到的)。纸上答案和程序输出对不上的地方,就是优先级认知的缺口。
30 秒实验:把 (a > b) && (c < d) || (e == f) 这类式子故意去掉括号,用 a=5,b=3,c=1,d=9,e=5,f=5 跑一遍——结果没变;但把 d 改成 0,去括号版本可能变结果(&& 与 || 谁先结合变了)。
五、常见误区
- "
==和<是一层的"——不是!==!=比<><=>=低一级。a < b == c会被算成(a < b) == c。 - "所有运算符都左结合"——赋值和
? :是右结合,连等号、链式三目都靠它。 - "优先级背下来就安全了"——背不出 50 行表,也没必要背。混用加括号才是真正的安全策略。
- "
a << 2 + 1这种写法很酷"——酷给编译器看,坑给读者跳。写代码是写给人看的,顺便给机器执行。
自测四问(点开对答案)
1. `10 + 3 * 4 % 5` 等于多少?——`12`(* 与 % 同级左结合:3×4=12,12%5=2,10+2=12)。 2. `x = y = z = 1;` 靠什么规则执行?——赋值的**右结合**,从右往左依次装。 3. `a < 5 && b > 2` 要加括号吗?——关系已高于逻辑,不加也对;但**建议加**,白送的可读性。 4. `&&` 和 `||` 谁优先级高?——`&&` 高。`a || b && c` 是 `a || (b && c)`。- ☐ 3.3 表达式(下一节)