短路求值是&&和||的强制语义:左侧已确定结果时右侧不执行;这使有副作用的右侧表达式可能被跳过,既保障安全(如空指针检查),也易引发bug(如i++未执行)。

短路求值是什么,为什么它会影响程序行为
短路求值不是优化技巧,而是 && 和 || 的强制语义:左侧表达式已能确定整个逻辑结果时,右侧**根本不会执行**。这意味着右侧若有副作用(如函数调用、自增、内存访问),它可能被跳过——这既是安全机制,也是常见 bug 源头。
&& 短路的典型误用场景
最常出问题的是把赋值或函数调用放在右侧,还默认它一定会运行:
-
if (ptr != NULL && *ptr == 0)安全,因为ptr为空时*ptr不会被求值 -
if (x > 0 && printf("x is positive\n"))——printf只在x > 0为真时才打印 - 错误写法:
if (a[i] && i++ ,若a[i]为假,i不会自增,循环逻辑就乱了
|| 短路带来的隐式条件分支
|| 在左侧为真时跳过右侧,常被用来做“默认值兜底”,但要注意右侧表达式是否依赖左侧状态:
-
int val = ptr ? *ptr : 0;等价于int val = ptr && *ptr ? *ptr : 0;,但更清晰;直接写int val = (ptr || (ptr = get_default())) ? *ptr : 0;就危险——ptr为真时get_default()根本不调用,看似省事,实则掩盖了意图 if (fd :只要fd无效就进分支,write不会触发;但如果想“无论 fd 是否有效都尝试 write”,就不能用||
和位运算符 &、| 混用导致的静默错误
& 和 | 是按位运算,**不短路**,且优先级低于 ==、!=,极易引发意料外的行为:
立即学习“C语言免费学习笔记(深入)”;
-
if (a & b == 0)实际等价于if (a & (b == 0)),几乎肯定不是你想要的,应写成if ((a & b) == 0) -
if (flag & FLAG_A | FLAG_B)会先算&再算|,但逻辑上你想表达的是“包含 A 或 B”,正确写法是if ((flag & FLAG_A) || (flag & FLAG_B)) - 编译器通常不会警告这类问题,运行时表现诡异,尤其在 flag 是枚举或宏定义时
短路特性本身不难理解,真正容易翻车的是把它当成“可选执行”的控制流来用,而忽略了它破坏了线性执行假设——任何依赖右侧必然发生的操作,都要重新审视。










