《C程序设计教程第8章.ppt》由会员分享,可在线阅读,更多相关《C程序设计教程第8章.ppt(46页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、n主讲人:第第8 8章章 位运算位运算 第第8 8章章 位运算位运算n位运算是对C语言功能的扩展,使C语言在控制系统中的应用更加灵活,运算效率更高并且更加节省存储空间。n本章主要内容:n8.1 位运算概述n8.2 位运算符的使用方法n8.3 位段n8.4 位运算举例第第8 8章章 位运算位运算8.1 8.1 位运算概述位运算概述n所谓位运算是指进行二进制数的运算。在计算机中真正执行的是机器指令,机器指令是由0和1所组成的二进制数表示的。每一个0或1称为一个“位”,要实现对计算机的操作就是实现对这些“位”的操作。nC语言所提供的位运算的功能,使得对计算机的操作更加灵活,更加高效,并且在一些控制领
2、域的应用中极大地节省了数据的存储空间,提高了程序的效率。nC语言所提供的位运算符如表8-1所示。8.1 8.1 位运算概述位运算概述 表8-1位运算符 运算符含义&|按位与按位或取反按位异或左移右移8.2 位运算符的使用方法位运算符的使用方法n8.2.18.2.1按位按位“与与”运算符(运算符(&)n8.2.28.2.2按位按位“或或”运算符(运算符(|)n8.2.3 8.2.3 按位按位“取反取反”运算符()运算符()n8.2.4 8.2.4 按位按位“异或异或”运算符(运算符()n8.2.5 8.2.5“左移左移”运算符(运算符()8.2.18.2.1按位按位“与与”运算符(运算符(&)n
3、按位与运算符“&”为二目(元)运算符,要求有两个运算量。作用是将两个运算量中的各个位分别对应进行“与”运算。如果两个相应的位都为1,则“与”运算后的结果为1;否则该位的结果为0。即:n0&0=0;n0&1=0;n1&0=0;n1&1=1;n例如,两个char类型的数据22和15,进行与运算,结果为6。8.2.18.2.1按位按位“与与”运算符(运算符(&)【例8.1】实现两个数据的与操作。程序的运行过程及结果如下:图8-1 例题8.1的执行结果 8.2.18.2.1按位按位“与与”运算符(运算符(&)按位与运算主要用于对一个数据中的某些位进行屏蔽,或者仅仅取出数据中的某些位中的数值。【例8.2
4、】屏蔽掉输入数据中的高四位,或者说取出输入数据中的低四位。程序的运行过程及结果如下:8.2.18.2.1按位按位“与与”运算符(运算符(&)图8-2 例题8.2的执行结果n从结果中可以看出,高4位数据被清零,低4位数据被保留。0 x0f称为屏蔽字。因此,当需要取出数据中的某些位时,只是把对应位的屏蔽字置1即可。例如,若要取出某一数据的1、3、5、7位数据,只是需要把屏蔽字设置为“0 xAA”或(10101010)2。8.2.28.2.2按位按位“或或”运算符(运算符(|)n按位或运算符“|”为二目(元)运算符,要求有两个运算量。作用是将两个运算量中的各个位分别对应进行“或”运算。如果两个运算量
5、的相应位中有一个为1,则“或”运算后的结果为1;否则该位的结果为0。即:n0|0=0;n0|1=1;n1|0=1;n1|1=1;8.2.28.2.2按位按位“或或”运算符(运算符(|)例如,两个char类型的数据22和15,进行或运算,结果为31。【例8.3】实现两个数据的或操作。程序的运行过程及结果如下:图8-3 例题8.3的执行结果 按位或操作主要用于对一个数据中的某些位置1。例如,若要使某一数据的第1、3、5、7位数据置1,只要使该数据和“0 xAA”进行或运算即可。8.2.28.2.2按位按位“或或”运算符(运算符(|)8.2.28.2.2按位按位“或或”运算符(运算符(|)【例8.4
6、】把输入数据的高四位置1,低四位保留。程序的运行过程及结果如下:图8-4 例题8.4的执行结果 8.2.3 8.2.3 按位按位“取反取反”运算符()运算符()n按位取反运算符“”为单目(元)运算符。作用是将一个二进制数按位取反,即将0变1,1变0。n例如,将char类型的数据22,进行取反,结果为233。【例8.5】把输入的数据进行取反操作。8.2.3 8.2.3 按位按位“取反取反”运算符()运算符()程序的运行过程及结果如下:图8-5 例题8.5的执行结果8.2.4 8.2.4 按位按位“异或异或”运算符(运算符()n按位异或运算符“”也称为XOR运算符,为二目(元)运算符,要求有两个运
7、算量。作用是将两个运算量中的各个位分别对应进行“异或”运算。规则为:若参加运算的相应位同号,则结果为0;异号则为1。即:n00=0;n01=1;n10=1;n11=0;8.2.4 8.2.4 按位按位“异或异或”运算符(运算符()n例如,两个char类型的数据22和15,进行异或运算,结果为25。【例8.6】实现两个数据的或操作。8.2.4 8.2.4 按位按位“异或异或”运算符(运算符()程序的运行过程及结果如下:图8-6 例题8.6的执行结果 8.2.5 8.2.5“左移左移”运算符(运算符()n按位左移运算符“”为二目(元)运算符,其作用是将一个数中各个二进制位全部左移若干位。高位左移后
8、溢出,低位补0。例如,x3。n左移一位相当于该数乘以21,左移n位相当于乘以2n,“22”左移3位,相当于乘以23为176。需要注意的是,此结论只适用于左移时溢出的高位中不包含1的情况。左移运算比乘法运算快很多。8.2.5 8.2.5“左移左移”运算符(运算符()【例8.7】把输入的数据进行左移操作。程序的第一次运行过程及结果如下:程序的第一次运行过程及结果如下:图8-7 例题8.7的第一次执行结果8.2.5 8.2.5“左移左移”运算符(运算符(”为二目(元)运算符,其作用是将一个数中各个二进制位全部右移若干位。右移运算对带符号数和无符号数有不同的操作。n1、对于带符号的数据,如果符号位为0
9、(即正数),右移后高位补入的全是0;如果符号位为1(即负数),则右移后,高位补入的全是1,这是为了保持原来的符号位,并实现右移一位相当于除2。n【例8.8】把输入的带符号数据进行右移操作。程序的第一次运行过程及结果如下:8.2.6 8.2.6“右移右移”运算符(运算符()8.2.6 8.2.6“右移右移”运算符(运算符()图8-9 例题8.8的第一次执行结果n第二次运行过程及结果如下:图8-10 例题8.8的第二次执行结果8.2.6 8.2.6“右移右移”运算符(运算符()运算过程示意图如图8-11(a)、(b)所示,其中带下划线部分为移出或移入数据。(a)数据为负数 (b)数据为正数图8-1
10、1 带符号位右移8.2.6 8.2.6“右移右移”运算符(运算符()n2、对无符号的数据,右移时高位全部补0。n【例8.9】把输入的无符号数据进行右移操作程序的运行过程及结果如下:图8-12 例题8.9的执行结果 8.2.6 8.2.6“右移右移”运算符(运算符()运行结果如图8-13所示,其中带下划线部分为移出或移入数据。与左移运算相同的是,只有当舍弃的低位中不包含1时,右移一位相当于除以2。图8-13 无符号位右移8.3 8.3 位段位段n8.3.1 8.3.1 位段的定义位段的定义 n8.3.2 8.3.2 位段的引用方式位段的引用方式8.3.1 8.3.1 位段的定义位段的定义nC语言
11、主要使用两种方式对二进制数进行操作,前面已经介绍了位运算,还有一种方式是使用位段。位段是由结构体实现的,是以位为单位来定义结构体中的成员的长度。例如:nstruct bittypennunsigned int a:2;nunsigned int b:1;nunsigned int c:3;nbitdata;n定义了一个位段结构体类型bittype,该类型具有a、b和c三个成员,每个成员分别占用2、1和3个二进制位,且合用一个字节,如图8-14所示。8.3.1 8.3.1 位段的定义位段的定义图8-14 位段的存储结构nC语言中对位段的处理非常灵活,如果想跳过某些位不用,就可以不给这些位段命名,
12、也就无法引用这些位段。例如:nstructbittypennunsigned inta:2;8.3.1 8.3.1 位段的定义位段的定义n unsigned int:2;nunsigned intb:1;nunsigned intc:3;nbitdata;n其中,a后面的2位没有被使用,如图8-15所示。图8-15 位段的存储结构8.3.1 8.3.1 位段的定义位段的定义 如果想忽略一个字节中剩余的位,使下一个位段从下一个字节开始存放,只要使用一个长度为0的无名字段即可。例如:nstructbittypennunsigned inta:2;nunsigned int:0;nunsigned
13、intb:3;nunsigned int:0;nunsigned intc:3;nbitdata;n共占用了3个字节的空间,如图8-16所示。8.3.1 8.3.1 位段的定义位段的定义图8-16 位段的存储结构n一个位段必须存储在同一个存储单元中,不能跨两个单元。如果一个单元的空间不能容纳下一个位段,则应该从下一个单元起存放该位段。n在一个结构体中可以混合使用位段和普通结构体变量。例如:8.3.1 8.3.1 位段的定义位段的定义nstructbittypenninta;nunsigned intb:2;nunsigned intc:3;nchard;nfloat e;nbitdata;8.
14、3.1 8.3.1 位段的定义位段的定义n上述结构体中,第一个成员是整型变量,占2个字节;后面两个位段b和c占1个字节;再后面是一个字符型和一个浮点型变量,各占1个字节和4个字节。n在位段的使用过程中需要注意的是,定义位段只能用int和unsigned int,不能用其它类型。8.3.2 8.3.2 位段的引用方式位段的引用方式n位段的引用方式与结构体成员的引用方式一致。例如bitdata.c=2。需要注意的是位段的取值范围,若bitdata.c占三位,则最大值只能是7。n与普通的结构体变量一样,可以通过指针来引用结构体中的位段成员,例如:np=&bitdata;np-c=2;8.3.2 8.
15、3.2 位段的引用方式位段的引用方式n但是不能取一个位段的地址,例如下面的用法是不合法的:n&因为地址是以字节为单位的,无法指向位。n位段在控制中非常有用,可以使用户方便、灵活的对字节中的位进行操作。并且位段的使用使几个数据放在同一个字节中,节省了存储空间。8.4 8.4 位运算应用举例位运算应用举例n【例8.10】设计一个程序,取出一个整数的第35位。n第一种实现方法:程序的执行过程及结果如下:图8-17 例题8.10的执行结果8.4 8.4 位运算应用举例位运算应用举例 其中,语句01是为了使要取出的数据移到最右端,如图8-18所示。语句02是使右移后产生的结果与二进制数00000111相
16、与,使结果仅仅保留低三位数据。图8-18 数据右移三位8.4 8.4 位运算应用举例位运算应用举例第二种实现方法:程序的执行过程及结果如下:图8-19 例题8.10第二种方法的执行结果n程序中采用了位段和共用体的方式,使位段中的每一位数分别对应数据的每一位,如图8-20所示,这样当需要输出数据的某一位数据时,只要输出对应位段中的值即可。8.4 8.4 位运算应用举例位运算应用举例图8-20 位段在共用体中的存储【例8.11】设计一个程序,使一个字节的高4位和低4位翻转。程序的执行过程及结果如下:8.4 8.4 位运算应用举例位运算应用举例图8-21 例题8.11的执行结果n其中语句01和02实
17、现取出a的低四位后,再向左移四位。实现把a的低四位数据存放在b的高四位地址中。语句03把a的高四位取出,存放在temp变量的低四位地址中。语句04把temp变量和b变量相或,完成对a变量高四位和低四位数据的交换。实现过程如图8-22所示。8.4 8.4 位运算应用举例位运算应用举例图8-22变量a高四位和低四位数据的交换n【例8.12】设计一个程序,实现逻辑右移。n所谓逻辑右移是在右移过程中,移出的低位数据移入到该数据的高位中,实现循环移动。程序的执行过程及结果如下:8.4 8.4 位运算应用举例位运算应用举例图8-23 例题8.12的执行结果n其中,变量a为需要右移的数据,n为要循环右移的位数。程序中,每次循环右移一位,判断,若移出位为1,则把右移后结果的最高位置1,如图8-24所示。8.4 8.4 位运算应用举例位运算应用举例图8-24 逻辑右移