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