1、短路求值(Short-circuit evaluation)
短路求值指的是,当运算符的左侧操作数已经足以确定整个表达式的值时,右侧操作数将不再被计算。对于 &&
(逻辑与),如果左侧操作数为 false
,则整个表达式一定为 false
,右侧操作数不会被计算。对于 ||
(逻辑或),如果左侧操作数为 true
,则整个表达式一定为 true
,右侧操作数不会被计算。
#include <stdio.h> int func1() { printf("func1 called\n"); return 0; } int func2() { printf("func2 called\n"); return 1; } int main() { if (func1() && func2()) { printf("Both are true\n"); } else { printf("At least one is false\n"); } return 0; }
2、求值顺序(Evaluation Order)
逻辑与(&&
)和逻辑或(||
)运算符的求值顺序是从左到右。这意味着左侧的操作数一定会先被计算,然后才是右侧的操作数(如果需要计算的话)。左侧操作数先求值,这对于依赖操作顺序的表达式非常重要。例如,在一些情况下,右侧操作数可能依赖左侧操作数的值。
#include <stdio.h> int main() { int x = 0; int y = 10; if (x != 0 && (y = y / x) > 2) { printf("Condition met\n"); } else { printf("Condition not met\n"); } return 0; }
3、短路求值的优点
性能优化,如果第一个操作数足以确定结果,则不需要计算第二个操作数,节省了计算资源。
#include <stdio.h> void printStringLength(char *str) { if (str && str[0] != '\0') { // 使用短路求值避免空指针解引用 printf("字符串长度大于0\n"); } else { printf("字符串为空或指针为NULL\n"); } } int main() { char *s1 = "Hello"; char *s2 = NULL; printStringLength(s1); // 输出:字符串长度大于0 printStringLength(s2); // 输出:字符串为空或指针为NULL return 0; }
防止运行时错误,可以避免不必要的计算,从而防止可能出现的错误(如上例的除以零错误)。
#include <stdio.h> int safeDivide(int a, int b) { return (b != 0 && a / b > 2) ? a / b : 0; // 使用短路求值避免除以零 } int main() { int result1 = safeDivide(10, 2); // 输出结果为5 int result2 = safeDivide(10, 0); // 输出结果为0(避免除以零) printf("结果1:%d\n", result1); printf("结果2:%d\n", result2); return 0; }
实现逻辑控制,在某些场景中,短路求值用于控制右侧表达式的求值,类似条件语句的作用。
4、非短路运算符(位运算符 & 和 |)
位运算符 &
和 |
不同于逻辑运算符 &&
和 ||
,它们不会进行短路求值。
#include <stdio.h> int func1() { printf("func1 called\n"); return 0; } int func2() { printf("func2 called\n"); return 1; } int main() { if (func1() & func2()) { printf("Both are true\n"); } else { printf("At least one is false\n"); } return 0; }