C语言逻辑运算符的用法以及汇总(附带优先级和结合性一览表)

 

顾名思义,C语言逻辑运算符是用来处理逻辑运算的。逻辑运算又称布尔运算,它主要用来处理“真值(非零值)”和“假值(零值)”之间的关系。


在高中数学中,我们就学过逻辑运算,例如 p 为真命题,q 为假命题,那么“p且q”为假,“p或q”为真,“非q”为真。在C语言中,也有类似的逻辑运算:
 

运算符 说明 优先级 结合性 举例
! 非运算,单目,对应数学中的“非”。! 右边的表达式为真时,结果为假;! 右边的表达式为假时,结果为真。 右结合 !a、!(2<5)
&& 与运算,双目,对应数学中的“且”。&& 两边的表达式都为真时,结果为真,否则结果为假。 左结合 1&&0、(9>3)&&(b>a)
|| 或运算,双目,对应数学中的“或”。|| 两边的表达式有一个为真时,结果为真,否则结果为假。 左结合 1||0、(9>3)||(b>a)

逻辑运算符和关系运算符的结果都是布尔类型;布尔类型只有两个取值,分别是真(true)和假(false);在C语言中,用 1 表示真,用 0 表示假。


同时,在逻辑运算或者条件判断的过程中,任何非零值(比如 10、926、-5)都会被视为真,只有零值(比如 0、'\0')才会被视为假。


在《C语言布尔类型 bool 用法》一节中提到,支持 C99 以及更高标准的编译器,可以用 bool 表示布尔类型,用 true 表示真(非 0 值),用 false 表示假(0 值)。下面的写法都是正确的:

int age = 20;
float score = 95.5;

bool isOK = true;
bool isAllowEnter = age>=18;
bool isExcellentStudent = isAllowEnter && score>90;

逻辑运算的结果

1) 与运算(&&)

参与运算的两个表达式都为真时,结果才为真,否则为假。例如:

5 && 0

5 为真,0 为假,相与的结果为假,也就是 0。再如:

(5>0) && (4>2)

5>0 的结果是 1,为真,4>2 结果是1,也为真,所以相与的结果为真,也就是1 。

2) 或运算(||)

参与运算的两个表达式只要有一个为真,结果就为真;两个表达式都为假时结果才为假。例如:

10 || 0

10 为真,0 为假,相或的结果为真,也就是 1。再如:

(5>0) || (5>8)

5>0 的结果是1,为真,5>8 的结果是0,为假,所以相或的结果为真,也就是 1。

3) 非运算(!)

参与运算的表达式为真时,结果为假;参与运算的表达式为假时,结果为真。例如:

!0

0 为假,非运算的结果为真,也就是 1。再如:

!(5>0)

5>0 的结果是 1,为真,非运算的结果为假,也就是 0。
 

输出逻辑运算的结果:

#include <stdio.h>
int main(){
    int a = 0, b = 10, c = -6;
    int result_1 = a&&b, result_2 = c||0;
    printf("%d, %d\n", result_1, !c);
    printf("%d, %d\n", 9&&0, result_2);
    printf("%d, %d\n", b||100, 0&&0);
    return 0;
}
运行结果:

0, 0
0, 1
1, 0

逻辑运算符的优先级

如果只谈三个逻辑运算符,它们的优先级从低到高依次是:

|| < && < !

也就是说,! 的优先级最高,&& 次之,|| 最低。

但是在实际的C语言编程中,逻辑运算符还会和关系运算符、算术运算符、赋值运算符等一起使用,所以我们有必要从整体上比较它们的优先级。逻辑运算符和其它运算符优先级从低到高依次为:

赋值运算符= < 逻辑运算符|| < 逻辑运算符&& < 关系运算符 < 算术运算符 < 逻辑运算符!

如果你想知道C语言中所有运算符的优先级和结合性,请转到:C语言运算符的优先级和结合性一览表
 
按照运算符的优先级顺序可以得出:

  • a>b && c>d  等价于  (a>b) && (c>d)
  • !b==c||d<a  等价于  ( (!b) == c ) || (d<a)
  • a+b>c&&x+y<b  等价于  ( (a+b) > c ) && ( (x+y) < b )


另外,逻辑表达式也可以嵌套使用,例如a>b && b || 9>ca || c>d &&  !p

结合优先级,再来看一下逻辑运算符的用法:

#include <stdio.h>
int main(){
    char c='k';
    int i=1, j=2, k=3;
    float x=3e+5, y=0.85;
    printf( "%d, %d\n", !x*!y, !!!x );
    printf( "%d, %d\n", x||i&&j-3, i<j&&x<y );
    printf( "%d, %d\n", i==5&&c&&(j=8), x+y||i+j+k );
    return 0;
}

运行结果:

0, 0
1, 0
0, 1


对于!x*!y,! 的优先级高于 *,所以先进行逻辑非运算,再进行乘法运算。x 和 y 分别为非 0,所以 !x 和 !y 分别为 0,所以 !x*!y 的结果为 0。
 

对于 !!!x,x 为非 0,所以 !x 为 0,!!x 为 1,!!!x 为 0。
 

对于 x||i&&j-3:先进行减法运算,计算 j-3 的值为非 0;然后进行逻辑与&&运算,计算 i&&(j-3) 的结果为 1;最后进行逻辑或||运算,计算 x||(i&&j-3) 的结果为 1。
 

对于 i<j&&x<y:先进行关系运算,求得 i<j 的值为 1,x<y 的值为 0;然后进行逻辑与运算,求得 (i<j) && (x<y) 的结果为 0。
 

对于 i==5&&c&&(j=8)。先进行比较运算和赋值运算,i==5 不成立,结果 0;而 (j=8) 赋值后的结果为 8,转换成布尔值后为 1。然后再进行逻辑运算,此时 && 是右结合性,所以先计算右边的 &&,得到 c&&(j=8) 的结果为 1;接着再计算左边的 &&,得到 (i==5) && (c&&(j=8)) 的结果为 0。
 

对于 x+ y||i+j+k:先进行算术运算,得到 x+y 和 i+j+k 的值都是非 0;然后再进行逻辑非||运算,得到整个表达式的结果为 1。

短路求值

C语言中的逻辑运算符使用短路求值,这意味着:

  • 在 && 运算中,如果第一个表达式的结果为假,就不会再计算第二个表达式,因为不管第二个表达式的结果是什么,都不会影响整个 && 运算的结果。
  • 在 || 运算中,如果第一个表达式的结果为真,就不会再计算第二个表达式,原理同上。


请看下面的例子:

#include <stdio.h>

int main() {
    int x = 5;
    int y = 0;
    
    // 由于 x > 10 为假,y != 0 不会被评估
    if (x > 10 && y != 0) {
        printf("This won't be printed\n");
    }
    
    // 由于 x > 0 为真,y != 0 不会被评估
    if (x > 0 || y != 0) {
        printf("This will be printed\n");
    }
    
    return 0;
}

输出结果:

This will be printed

综合示例

逻辑运算符在C语言中有很多应用场景,这里不妨举几个例子。

1) 判断闰年

一个年份是闰年的条件是:能被 4 整除但不能被 100 整除,或者能被 400 整除。这个条件被翻译成C语言的逻辑表达式就是:

(year % 4 == 0 && year % 100 != 0) || year % 400 == 0

完整的实现代码如下:

#include <stdio.h>

int main() {
    int year = 0;

    printf("请输入年份:");
    scanf("%d", &year);

    if( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 ){
        printf("%d 是闰年\n", year);
    }
    else {
        printf("%d 不是闰年\n", year);
    }

    return 0;
}

运行结果:

请输入年份:2024
2024 是闰年

2) 判断元音字母

26 个字母中的元音字母只有 a、e、i、o 和 u 六个,只要输入的字符是其中之一,就是元音字母。请看下面的代码:

#include 
#include 

int main() {
    char ch = 0;

    printf("请输入一个英文字母:");
    scanf("%c", &ch);
    ch = tolower(ch);  // 转换为小写字母

    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
        printf("%c 是元音字母\n", ch);
    }else {
        printf("%c 不是元音字母\n", ch);
    }

    return 0;
}

输出结果:

请输入一个英文字母:U
u 是元音字母