3.8.4 位运算符

位运算符是对字节或字的二进制位(bit)进行逐位逻辑处理或移位的运算符。C51语言中的位运算符如下所示。

❑“&”运算符:进行逻辑与(AND)运算。

❑“|”运算符:进行逻辑或(OR)运算。

❑“^”运算符:进行逻辑异或(XOR)运算。

❑“~”运算符:进行按位取补(NOT)运算。

❑“>>”运算符:进行右移运算。

❑“<<”运算符:进行左移运算。

位运算符的操作对象整型和字符型数据的字节或字,位操作不能用于float、double、long double、void或其他聚合类型。支持全部的位运算符,表明C51可以进行汇编语言所具有的位运算,因此C51语言既具有高级语言的特点,也具有低级语言的功能。

位运算中的AND、OR和NOT(1的补码)的真值表与逻辑运算等价,唯一不同的是,位操作是首先将操作数分解为二进制,然后逐位进行运算的。下面分别介绍各种位运算符的用法。

1.按位与运算符

按位与运算符是将两个操作数按二进制展开,然后将对应位进行逻辑与运算。按位与运算符“&”是二目运算符,即要求有两个源操作数。如果操作数对应的二进制位均为1,则逻辑与的结果为1;否则,则逻辑与的结果为0。

例如,将a=56和b=37进行按位与运算。将56展开为二进制是00111000,将37展开为二进制是00100101。按位与运算的结果为a&b=32(00100000)。

注意这里需要区分位运算符“&”和关系逻辑运算符“&&”,关系逻辑运算符“&&”的结果不是0就是1。而位运算符“&”的结果通过逐位处理,结果可为0和1之外的其他值。例如a=56和b=37,a&&b=1,而a&b=32。

2.按位或运算符

按位或运算符是将两个操作数按二进制展开,然后将对应位进行逻辑或运算。按位或运算符“|”也是二目运算符,即要求有两个源操作数。如果对应的二进制位均为0,则逻辑或的结果为0;否则,则逻辑或的结果为1。

例如,将a=56和b=37进行按位或运算。将56展开为二进制是00111000,将37展开为二进制是00100101。按位或运算的结果a|b=61(00111101)。

3.按位非运算符

按位非运算符是将操作数按二进制展开,然后将每一位进行取反操作,即将0变为1,将1变为0。按位非运算符“~”是一目运算符,只需要一个源操作数。

例如,将a=5 6进行按位取反运算。5 6的二进制表示为0 0 111 0 0 0,结果~a=1 9 9(11000111)。

说明按位非运算得到的结果和源操作数是逐位相反的,因此这两者进行按位或运算的结果每个二进制位均为1,即对应十进制255。这样可以通过255减去源操作数得到按位非运算的结果。例如56按位非的结果为255-56=199,和上面的结果相同。

4.按位异或运算符

按位异或运算符是将两个操作数按二进制展开,然后将对应位进行逻辑异或运算。按位异或运算符“^”也是二目运算符,需要两个源操作数。如果对应的二进制位均为0或均为1,则逻辑或的结果为0;否则,只要对应位不相同,则逻辑异或的结果为1。异或运算的逻辑真值如表3.7所示。

例如,将a=56和b=37进行按位异或运算。将56展开为二进制是00111000,将37展开为二进制是00100101。按位异或运算的结果a|b=29(00011101)。

3.8.4 位运算符 - 图1

提示在有些高级程序设计语言中,将运算符“^”作为求幂运算,要注意区分。

5.移位运算符

移位运算符是将源操作数按二进制展开,然后将对应位按要求进行移动。C51中移位运算符有两种,分别将操作数的各位按要求向左或向右移动,其使用格式如下。

❑左移语句形式是:变量名(或操作数)<<左移位数

❑右移语句形式是:变量名(或操作数)>>右移位数

在C51程序中使用移位运算符需要注意如下三点。

❑C51语言中的移位不是循环移位,当某位从一端移出时,另一端移入0。从一端移出的位并不送回到另一端去,移去的位永远丢失了,同时在另一端补0。

❑右移运算,对无符号位数左端补0,称为“逻辑右移”;如果为负数,即符号位为1,则左端补1,这种补1保持负号的方法称为“算术右移”。

❑左移运算有时可用来做乘法,右移运算有时可用来做除法。例如,x=7,将其进行移位操作,结果如表3.8所示。

从表中可以看出,每左移一位,结果乘2,每右移一位相当于被2除。注意表中x<<2后,原x的信息已经丢失了,因为一位“1”已经从一端移出。因此,需要注意这种用法的范围。

6.程序示例

前面具体介绍了各个位运算符,这里举例来演示位运算符在程序中的具体应用。位运算符的程序示例如下。

3.8.4 位运算符 - 图2


include<stdio.h>//头文件

void main()//主函数

{

int a,b,c;//定义变量

a=23;//变量赋值

b=217;

c=a&b;//按位与运算

printf(“a&b=%d\n”,c);//输出结果

c=a|b;//按位或运算

printf(“a|b=%d\n”,c);//输出结果

c=a^b;//按位异或运算

printf(“a^b=%d\n”,c);//输出结果

c=~a;//按位取反运算

printf(“~a=%d\n”,c);//输出结果

c=a<<3;//左移两位

printf(“a<<3=%d\n”,c);//输出结果

c=b>>2;//右移三位

printf(“b>>2=%d\n”,c);//输出结果

}


该程序可在KeilµVision3集成开发环境中运行,执行结果如下。


a&b=17

a|b=223

a^b=206

~a=-24

a<<3=184

b>>2=54


读者可以参考前面介绍的内容,分析一下程序运行的结果和预期的是否一致。读者同样可以采用不同数进行运算,从而熟练掌握位算符的操作。