首页 > 编程笔记

C语言逻辑运算符和表达式

什么是逻辑运算?逻辑运算又称为布尔运算,通常用来测试真假值,“真”即事件“成立”,“假”即事件“不成立”,判断的结果只有两种情况。在C语言中用数字“1”和“0”表示真假两种状态,这两个值称为“逻辑值”。

当判断一个复杂的事件是否成立时,如果这个事件由 n 个状态构成,例如一个房间有两个门——A 门和 B 门。要进房间从 A 门进可以,从 B 门进也可以。用语言来描述是“要进房间去,可以从 A 门进或者从 B 门进”,如何用符号来表示呢?

假设,能否进房间用符号 C 表示,C 的值为 1 表示可以进房间,为 0 表示进不了房间;A 和 B 的值为 1 时表示门是开着的,为 0 表示门是关着的。那么能否进门一共有 4 种可能:

逻辑运算符

逻辑运算符主要用于逻辑运算,包含“&&”(逻辑与)、“||”(逻辑或)、“!”(逻辑非)3种。逻辑运算符的真值表如下。
条件a 条件b a&&b a||b !a
1 1 1 1 0
1 0 0 1 0
0 1 0 1 1
0 0 0 0 1

其中,“!”是单目运算符,而“&&”和“||”是双目运算符。

逻辑表达式

逻辑运算符把各个条件表达式连接起来组成一个逻辑表达式,如 a&&b、1||(!x)。逻辑表达式的值也只有两个——0 和 1。0 代表结果为假,1 代表结果为真。

例如,当 x 为 0 时,x<-2&&x>=5 的值为多少?

当 x=0 时,0<-2 结果为假,值等于 0;当 0&&“任何值”时其结果仍为 0,所以在此系统不再判断 x>=5 的结果,可以直接得到整个式子的结果。

当对一个量(可以是单一的一个常量或变量)进行判断时,C语言编译系统认为 0 代表“假”,非 0 代表“真”。例如,当 a=4,则:

应用举例

本文通过两个范例来学习逻辑运算符和表达式的使用。

【示例1】试写出判断某数 x 是否小于 -2 且大于等于 5 的逻辑表达式。当 x 值为 0 时,分析程序运行结果。
#include<stdio.h>
int main()
{
    int x,y; /*定义整型变量x,y */
    x=0;
    y=x<-2 && x>=5; /*将表达式的值赋给变量y*/
    printf("表达式x<-2 && x>=5的值为%d\n",y); /*输出结果*/
}
运行结果:
表达式x<-2 && x>=5的值为0

本范例中判断某数x是否小于 -2 且大于等于 5 的逻辑表达式可写为“x<-2&&x>=5”,因为是两个条件同时成立,应使用“&&”运算符将两个关系表达式连接在一起,所以表达式从整体上看是逻辑表达式,而逻辑符左右两边的运算分量又分别是关系表达式。

该例先计算 x<-2,不成立,值为 0,因为后面的逻辑运算符是 &&,所以不管 x>=5 的值为真还是假,整个表达式的值都为假,所以系统不再计算 x>=5 的值,直接可确定整个表达式的值即为 0。

【示例2】试判断给定的某年 year 是否为闰年。(闰年的条件是符合下面两个条件之一:能被 4 整除,但不能被 100 整除;能被 400 整除。)
#include<stdio.h>
int main()
{
    int year;  /*定义整型变量year表示年份*/
    printf("请输入任意年份:");  /*提示用户输入*/
    scanf("%d",&year);  /*由用户输入某一年份*/
    if(year%4==0&&year%100!=0||year%400==0)  /*判断year是否为闰年*/
        printf("%d是闰年\n",year);  /*若为闰年则输出year是闰年*/
    else
        printf("%d不是闰年\n",year);  /*否则输出year不是闰年*/
}
运行结果1:
请输入任意年份:2019
2019不是闰年

运行结果2:
请输入任意年份:2008
2008是闰年

在本例中,用了 3 个求余运算符判断某一个数能否被整除。判断 year 是否为闰年有两个条件,这两个条件是或的关系,第1个条件可表示为 year%4==0&&year%100!=0,第2个条件可表示为 year%400==0。两个条件中间用“||”运算符连接即可。即表达式可表示为 (year%4==0&&year%100!=0)||(year%400==0)。

由于 ! 的优先级高于算术运算符,算术运算符的优先级高于关系运算符,关系运算符的优先级高于逻辑运算符,&& 的优先级又高于 ||,因此上式可以将括号去掉,写为:

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

如果判断 year 为平年(非闰年),可以写为:

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

因为是对整个表达式取反,所以要用圆括号括起来。否则就成了 !year%4==0,由于 ! 的优先级高,会先计算 !year,因此后面必须用圆括号括起来。

本例中使用了 if-else 语句,可理解为若 if 后面括号中的表达式成立,则执行 printf("%d是闰年\n",year); 语句,否则执行 printf("%d不是闰年\n",year); 语句。

如果要判断变量 a 的值是否为 0~5,很自然想到了这样一个表达式:

if(0<a<5)

这个表达式没有什么不正常的,编译可以通过。但是现在仔细分析一下if语句的运行过程,表达式 0<a<5 中首先判断 0<a,如果 a>0 则为真,否则为假。

设 a 的值为 3,此时表达式结果为逻辑真,那么整个表达式 if(0<a<5)成为 if(1<5)(注意这个新表达式中的1是 0<a 的逻辑值),这时问题就出现了,可以看到当变量a的值大于0的时候总有 1<5,所以后面的 <5 这个关系表达式是多余的。

另外,假设a的值小于0,也会出现这样的情况。由此看来这样的写法肯定是错误的。

正确的写法应该是:

if((0<a)&&(a<5))  /*如果变量a的值大于0并且小于5*/

优秀文章