C语言 逻辑运算符短路求值特性

C和C++中,逻辑运算符 &&(逻辑与)和 ||(逻辑或)具有短路求值特性,且操作数的求值顺序是规定好的。也就是在某些条件下,编译器可以跳过对某些操作数的求值,直接返回结果。这种行为在语言标准中有严格的定义。

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;
}

推荐阅读
cjavapy编程之路首页