赋值运算符=优先级最低,a = b == c等价于a = (b == c),导致语义错误、静默编译和调试困难;解决方法是显式加括号或拆分为两步。

++ 和 + 看起来都带加号,但优先级差两级;&& 和 || 都是逻辑运算,可 && 会先于 || 执行;最常被误判的是赋值运算符 = ——它比几乎所有比较和算术运算符的优先级都低,写 if (a = b == c) 实际等价于 if (a = (b == c)),不是你想的 if ((a = b) == c)。
为什么 a = b == c 不等于 (a = b) == c
因为 == 优先级(第8级)远高于 =(第15级),所以编译器先算 b == c,再把结果赋给 a。这会导致两个问题:
- 语义错误:本想判断
a是否等于b再跟c比,结果变成把布尔结果存进a - 静默编译:C++ 允许
int a; a = true;,不会报错,但逻辑已崩 - 调试困难:
a的值突变为0或1,而你还在检查b和c的原始值
解决办法只有显式加括号:if ((a = b) == c),或者更好——拆成两步:a = b; if (a == c)。
++i 和 i++ 在复杂表达式里怎么结合
后缀 ++(如 i++)优先级为第2级,高于前缀 ++(第3级);这意味着 *p++ 等价于 *(p++),而不是 (*p)++。常见踩坑场景:
-
arr[i++] = x;→ 先用i当前值当索引,再自增;arr[++i] = x;→ 先自增再用新i索引 -
func(i++, i);行为未定义:同一表达式中对i读+写,且无序点分隔 -
int* p = arr; *p++ + *p;:第一次*p++取arr[0],p指向arr[1];第二次*p取arr[1]—— 但这是未定义行为(C++17 前),因++和*无明确求值顺序
什么时候必须靠括号,不能只背优先级表
优先级表只解决“谁先算”,不解决“谁和谁配对”。例如:
-
a & b == c:按表==(8级)高于&(9级),所以是a & (b == c),而非(a & b) == c—— 即使你本意是位与后比较 a :<code>+(5级)高于(6级),所以是 <code>a ,符合直觉;但 <code>a + b 就是 <code>(a + b) ,容易忽略-
!a & b:逻辑非!(3级)高于按位与&(9级),所以是(!a) & b,不是!(a & b)
结论:只要涉及混合类型运算符(比如逻辑+位、算术+关系、赋值+比较),别赌记忆,加括号。括号不是软弱,是明确意图。
右结合运算符的陷阱:连续赋值和三目嵌套
= 和 ?: 是右结合,意味着 a = b = c 解析为 a = (b = c),这没问题;但三目嵌套就容易漏括号:
-
cond1 ? val1 : cond2 ? val2 : val3等价于cond1 ? val1 : (cond2 ? val2 : val3),符合预期 - 但
cond1 ? cond2 ? val1 : val2 : val3会被解析为cond1 ? (cond2 ? val1 : val2) : val3,如果本意是(cond1 ? cond2 : something) ? ...,那就错了 - 更危险的是混用:
a ? b : c = d→ 因=优先级最低,实际是a ? b : (c = d),不是(a ? b : c) = d(后者非法,因三目结果不可赋值)
真正容易被忽略的,是右结合性在嵌套时产生的隐式分组层级 —— 它不报错,但一旦条件逻辑变复杂,读代码的人第一反应往往是左结合,从而误判执行流。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











