第11章 位运算

上传人:今*** 文档编号:107170531 上传时间:2019-10-18 格式:PPT 页数:39 大小:270KB
返回 下载 相关 举报
第11章 位运算_第1页
第1页 / 共39页
第11章 位运算_第2页
第2页 / 共39页
第11章 位运算_第3页
第3页 / 共39页
第11章 位运算_第4页
第4页 / 共39页
第11章 位运算_第5页
第5页 / 共39页
点击查看更多>>
资源描述

《第11章 位运算》由会员分享,可在线阅读,更多相关《第11章 位运算(39页珍藏版)》请在金锄头文库上搜索。

1、第11章 位运算,11.1 位运算符 11.2 位运算符的运算功能 11.3 位段 习题11,11.1 位运算符,计算机中的位运算是针对二进制代码进行的。每一个二进制位的取值只有0或1。位运算符的操作对象是一个二进制位的集合,如一个字节(8 bit)。 位运算符共有6种,即 、&、| 和 ,分别表示按位取反、左移位、右移位、按位与、按位或和按位异或,见表11-1所示。,表11-1 位 运 算 符,按位操作的情况,见表11-2所示,其中,a和b分别表示一个二进制位。,表11-2 按位逻辑运算,移位运算符是将一个数的二进制位向左或向右移若干位。每向左移一位,就相当于对操作对象乘以2;每向右移一位,

2、就相当于对操作对象除以2。向左移位时,右边补0,高位溢出舍弃不用;向右移位时,对无符号数左边补0。在C语言中,对有符号数,若该数为正,则左边补0;若该数为负,则左边补1。 11.1.1 按位取反 求反运算符“”为单目运算符,具有右结合性。其功能是对参与运算的数的各二进位按位求反。例如,9的运算为 (0000 0000 0000 1001)=1111 1111 1111 0110 即将其操作对象中的所有二进制位全部改变状态,即“逢0变1,逢1变0”。,又如,八进制数0217(即二进制数1000 1111),其按位取反后为八进制数0160(即二进制数0111 0000),即 1000 1111 0

3、111 0000 11.1.2 移位 移位运算符有左移运算符和右移运算符两种。 1. 左移运算符 左移运算符“”是双目运算符。其功能是将一个数的各二进制位全部左移若干位(左丢弃,右补0),由“”右边的数指定移动的位数。,左移运算符的一般书写格式为 表达式1 表达式2 其中,“表达式1”是被左移的对象,“表达式2”给出左移的位数。例如: a=1; a=a2; 将a的二进制数左移2位,右补0。此时a的值为4。 若左移时舍弃的高位不包含1,则数每左移一位,相当该数乘以2。,2. 右移运算符 右移运算符是将其操作对象向右移动指定的位数,每右移1位相当于除以2,移n位相当于除以2的n次方。在进行右移时,

4、右边移出的二进制位被舍弃。 右移运算符的一般书写格式为 表达式1 表达式2 其中,“表达式1”是被右移的对象,“表达式2”给出右移的位数。例如: a=15; a=a2; 示把0000 1111右移为0000 0011(十进制3)。,应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1取决于编译系统的规定。Turbo C和很多系统规定为补1。 11.1.3 按位与 按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。参与运算的数以补码的方式出现。 按位与的一般书写格式为 表达式1 & 表达式2 其中,“

5、表达式1”和“表达式2”均为整型表达式。,按位与的运算原则为:当两个操作对象的相应二进制位都为1时,则该位的结果为1,否则为0,即“两1为1,其余为0”。 但要注意,按位与运算时,两个表达式之间用“&”符号,而逻辑与时,两个表达式之间用“&”符号,所以,一定要注意不要弄错。 例如,11&5可写成算式如下: 0000 1011 & 0000 0101 0000 0001,所以,11,b=a5; /* a右移5位,将右移后的值赋给b */ b=b 运行结果: input a number: 255 a=255 b=7,【例11-2】利用按位与来获取指定位的值。 假设x是一般的unsigned类型的

6、整型数(2个字节),现在需要获取其低字节的值,这时,只需将x与0377相与即可。例如: y = x & 0377 式中,x的二进制表示为0101 0001 0111 0010,0377的二进制表示为0000 0000 1111 1111,y的二进制表示为0000 0000 0111 0010。即 0101 0001 0111 0010 & 0000 0000 1111 1111 0000 0000 0111 0010,【例11-3】利用按位与来测试指定的位是否为0。 假设需测试上例中x的从左数第4位是否为0, 则只需将它与010000(八进制)按位与(即y=x & 010000)。若y为0,则

7、说明被测位为0,否则为1。 由于x的二进制表示为0101 0001 0111 0010,010000的二进制表示为0001 0000 0000 0000,因此,计算结果为0001 0000 0000 0000。即 0101 0001 0111 0010 & 0001 0000 0000 0000 0001 0000 0000 0000,11.1.4 按位或 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的两个二进位有一个为1,结果位就为1,即“两0为0,其余为1”。参与运算的两个数均以补码的形式出现。 按位或的一般书写格式为 表达式1 | 表达式2 其中,“

8、表达式1”和“表达式2”均为整型表达式。 但要注意,按位或运算时,两个表达式之间用“|”符号,而逻辑或时,两个表达式之间用“|”符号,所以,一定要注意不要弄错。,例如,9|5可写成算式如下: 0000 1001 | 0000 0101 0000 1101(十进制为13) 所以,9|5的值为13。,【例11-4】利用按位或将指定位设置为1。 假设将x的从右数第3位(二进制位)设置为1,则只需执行如下的表达式即可。 x = x | 04 式中,x的二进制表示为0101 0001 0111 0010,04的二进制表示为0000 0000 0000 0100,按位或后的x值为0101 0001 011

9、1 0110。即 0101 0001 0111 0010 | 0000 0000 0000 0100 0101 0001 0111 0110,【例11-5】左移、右移、按位或和按位与运算符举例。 #include “stdio.h“ main( ) char a=a,b=b; int p,c,d; p=a; p=(p8; printf(“a=%dnb=%dnc=%dnd=%dn“,a,b,c,d); ,运行结果: a=97 b=98 c=97 d=98,11.1.5 按位异或 按位异或运算符“”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两数对应的二进位相异时,结果为1。 按位

10、“异或”的一般书写格式为 表达式1 表达式2 其中,“表达式1”和“表达式2”均为整型表达式。 按位异或的运算原则为:当两个操作对象的相应位相同时,则该对应位的结果为0,否则为1,即“相同为0,不同为1”。即 0 0 = 0;0 1 = 1;1 0 = 1;1 1 = 0 按位异或也可以称不进位加,即两个操作对象执行二进制相加,但不向高位进位。,例如,95可写成算式如下: 0000 1001 0000 0101 0000 1100(十进制为12) 所以,95的值为12。 利用按位异或可使一个数的各二进制位翻转。例如要使x的各位翻转,只需执行下面的表达式。 x = x 0177777 其中,x的

11、二进制表示为0101 0001 0111 0010,异或后的结果为1010 1110 1000 1101。,11.2 位运算符的运算功能,【例11-6】将整型数据n的后5位数据置为0,其余各位不变。 #include main( ) int n ; printf(“input n : “) ; scanf(“%d“ , ,【例11-7】实现向左循环移位。 #include main( ) unsigned a , b , c ; int n ; printf(“input a : “) ; scanf(“%o“ , ,【例11-8】将一个整型数据的各位以倒序输出。 #include main(

12、 ) unsigned a , b ; int i ; printf(“input a : “) ; scanf(“%o“ , ,【例11-9】取一个单元a的某几位到另一个单元b。 #include void yiwei(pa , pb , st1 , st2 , n1) unsigned *pa , *pb ; int st1 , st2 , n1 ; unsigned c , d ; int move ; move=st1-st2 ; c=(00) *pb=(c ,main( ) int a1 , b1 , n ; unsigned a , b ; printf(“input a : n“

13、) ; scanf(“%o“ , ,printf(“input the start num b1 : n“) ; scanf(“%d“ , ,11.3 位段,有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如,在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,语言又提供了一种数据结构,称为“位段”。 所谓“位段”,是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位段来表示。,1. 位段的定义和位段变量的说明 1) 位段的

14、定义 位段定义与结构定义相仿,其格式为 struct 位段结构名 位域列表 ; 其中,位域列表的格式为 类型标识符 位域名:位域长度 例如: struct packed_data, unsigned a:2; unsigned b:6; unsigned c:4; unsigned d:4; int i; data ;,位段变量data的数据存储情况如图11.1所示。,图11.1 位段变量的存储,位段变量的说明与结构变量说明的方式相同。可采用先定义后说明,同时定义说明或者直接说明这3种方式。 2) 说明 对于位段的定义尚有以下几点说明。 (1) 一个位域必须存储在同一个字节中,不能跨两个字节。

15、如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域,也可以有意使某位域从下一单元开始。例如:,struct bs unsigned a:4 unsigned :0 /* 空域 */ unsigned b:4 /* 从下一单元开始存放 */ unsigned c:4 在这个位段定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。 (2) 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度。也就是说,不能超过8位二进位。,(3) 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如: struct k int a

16、:1 int :2 /* 该2位不能使用 */ int b:3 int c:2 ; 从以上分析可以看出,位段在本质上就是一种结构类型,不过其成员是按二进位来分配的。,2. 位域的引用 位域引用的一般格式为 位段变量名.位域名 位域允许用各种格式输出。 【例11-10】定义一个位段变量,对变量的位域赋值,输出位域的值。 #include “stdio.h“ main( ) struct bs /* 定义位段bs */, unsigned a:1; unsigned b:3; unsigned c:4; bit,*pbit; /* 定义位段变量bit和指针pbit */ bit.a=1; /* 第10行 */ bit.b=7; /* 第11行 */ bit.c=15; /* 第12行 */ printf(“

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号