C语言中&&和||采用短路求值:&&左侧为假时跳过右侧,||左侧为真时跳过右侧,这是标准规定而非优化;影响空指针检查、副作用执行、默认值逻辑及隐式类型转换。

为什么 && 和 || 不总是两边都执行?
因为 C 语言规定它们是「短路求值」操作符:一旦结果已确定,就不再计算右侧表达式。&& 左边为假时整个结果必为假,|| 左边为真时整个结果必为真——此时右边直接跳过。
这不只是优化,而是语言标准行为(C11 §6.5.13 / §6.5.14),影响程序逻辑和副作用。
- 常见错误现象:
if (ptr != NULL && ptr->data > 0)能安全避免空指针解引用;但若写成if (ptr->data > 0 && ptr != NULL),运行时大概率崩溃 - 副作用陷阱:若右侧有函数调用(如
func() || printf("yes")),它可能根本不执行 - 性能影响:短路能省掉不必要的计算,尤其在右侧涉及系统调用、文件读取或复杂判断时
&& 的实际使用场景和参数顺序讲究
左侧应放「计算快、失败概率高、起保护作用」的条件;右侧放「代价高、依赖左侧成立」的逻辑。
- 检查指针有效性后再访问成员:
if (buf != NULL && len > 0 && write(fd, buf, len) == len) - 避免除零:
if (denom != 0 && numerator % denom == 0) - 错误写法:
if (strlen(s) > 5 && s[5] == 'x')——strlen是 O(n),且s可能为空指针;应先判空再算长度
|| 的短路特性常被用来做默认值或备选逻辑
|| 的短路意味着「只要左边为真就停」,所以常用于 fallback 场景,但要注意:它判断的是「非零即真」,不是「是否为空指针」或「是否为 NULL 字符串」。
立即学习“C语言免费学习笔记(深入)”;
- 给指针变量赋默认值(需配合三目):
char *p = maybe_null ?: "default";(注意这是 GNU 扩展,标准 C 应写maybe_null ? maybe_null : "default") - 模拟「或执行」逻辑:
fd = open(path1, O_RDONLY) || open(path2, O_RDONLY);—— 错!open失败返回 -1(非零),-1 || ...恒为真,且右侧仍会执行。正确写法必须显式比较:(fd = open(path1, O_RDONLY)) != -1 || (fd = open(path2, O_RDONLY)) != -1 - 日志或调试触发:
verbose && printf("debug: x=%d\n", x);是惯用法,等价于if (verbose) printf(...);
容易被忽略的整型隐式转换问题
C 中没有布尔类型(_Bool 是后来加的),&& 和 || 返回的是 int:真为 1,假为 0。但操作数本身可以是任意标量类型,都会被当作「非零即真」来判断。
- 坑点:
char c = 0xFF;,c在有符号 char 下是 -1,-1 || anything为真,但你可能误以为它是“无效字节” - 更隐蔽的问题:
if (ptr && *ptr)—— 若*ptr是char且值为\xFF(有符号时为 -1),条件仍为真;但若本意是“非空且首字节非零”,那就错了 - 建议:对字符/字节做逻辑判断时,显式转成无符号或与 0 比较,例如
if (ptr && (unsigned char)*ptr != 0)











