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

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

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&&x+y c ) && ( (x+y) < b )

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

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

#include

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

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

对于 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

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

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 是元音字母