《第13章 位运算.ppt》由会员分享,可在线阅读,更多相关《第13章 位运算.ppt(19页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第十三章 位运算学习目标l位运算的有关概念和运算规律l位段的概念课程内容l13.1 概述l13.2 位运算符和位运算l13.3位段 13.1 概述概述 C语言程序设计最大的一个特点就是可以对计算机硬可以对计算机硬件进行操作,其操作主要是通过位运算实现的。件进行操作,其操作主要是通过位运算实现的。位运算很适合编写系统软件的需要,是C语言的重要特色。在计算机用于检测和控制领域中要用到位运算的知识。所谓位运位运算算就是指进行二进制的运算就是指进行二进制的运算。在系统软件中,常要处理二进制的问题。例如,将一个存储单元中的各二进制左移或者右移一位,两个数按位相加等。C语言提供位运算的功能,与其他高级语言
2、相比,显然具有很大的优越性。C语言提供语言提供6种位运算符种位运算符运算符运算符含义含义例子例子运算功能运算功能&按位与按位与a&ba和和b按位与按位与|按位或按位或a|ba和和b按位或按位或按位异或按位异或aba和和b按位异或按位异或按位求反按位求反aa按位取反按位取反左移位左移位a右移位右移位b3b右移右移3位位说明:说明:(1)为单目运算符为单目运算符,其余均为,其余均为双目运算符双目运算符,优先级高低顺序:,优先级高低顺序:按位求反按位求反 移位移位 按位与按位与&按位异或按位异或 按位或按位或|(2)运算量只能是运算量只能是整型整型或或字符型数据字符型数据,浮点数不能参与运算浮点数不
3、能参与运算(3)参与运算时,操作数都必须转换成参与运算时,操作数都必须转换成二进制形式二进制形式,然后再执行,然后再执行按位运按位运算算 13.2 位运算符和位运算如果左移出的位如果左移出的位不是不是1 1,则左移操作相当于,则左移操作相当于乘法乘法操作,操作,左移一位相当于原数乘以左移一位相当于原数乘以2 2,左移,左移n n位,则相当于位,则相当于原数原数乘以乘以2 2n nn左移位运算符左移位运算符 格式格式:xx位数位数规则规则:使操作数的各位左移,低位补使操作数的各位左移,低位补0 0,高位,高位溢出。例:溢出。例:52=205格式格式:xx位数位数规则规则:使操作数的各位右移,移出
4、的低位舍弃,使操作数的各位右移,移出的低位舍弃,高位补符号位。例:高位补符号位。例:20 2=520 2=5左移操作相当于左移操作相当于除法除法操作,右移一位相当于原数除以操作,右移一位相当于原数除以2 2,右移,右移n n位,则相当于位,则相当于原数除以原数除以2n2n【例例13.1】左移位左移位1#include 2 void main()3 4 int a=-1;5 int i=0;6 for(i=0;i17;i+)7 8 printf(%d%d=%dt,a,i,ai);9 printf(0 x%x%d=0 x%xn,a,i,ai);10 11 运行结果如下:运行结果如下:-10=-10
5、 xffff0=0 xffff-11=-20 xffff1=0 xfffe-12=-40 xffff2=0 xfffc-13=-80 xffff3=0 xfff8-14=-160 xffff4=0 xfff0-15=-320 xffff5=0 xffe0-16=-640 xffff6=0 xffc0-17=-1280 xffff7=0 xff80-18=-2560 xffff8=0 xff00-19=-5120 xffff9=0 xfe00-110=-1024 0 xffff10=0 xfc00-111=-20480 xffff11=0 xf800-112=-40960 xffff12=0 x
6、f000-113=-81920 xffff13=0 xe000-114=-16384 0 xffff14=0 xc000-115=-32768 0 xffff15=0 x8000-116=0 0 xffff16=0 x0 整型数据是采用补码表示的。每左移一位相当于数据乘以整型数据是采用补码表示的。每左移一位相当于数据乘以2 2,当移位结果超出数据表示范围时,结果就不再正确。,当移位结果超出数据表示范围时,结果就不再正确。【例例13.2】右移位右移位1#include 2 void main()3 4 int a=0 xc57f;5 int i;6 for(i=0;i%d=%dt,a,i,ai)
7、;9printf(0 x%x%d=0 x%xn,a,i,ai);10 11 运行结果如下:运行结果如下:-149770=-14977 0 xc57f0=0 xc57f-149771=-7489 0 xc57f1=0 xe2bf-149772=-3745 0 xc57f2=0 xf15f-149773=-1873 0 xc57f3=0 xf8af-149774=-937 0 xc57f4=0 xfc57-149775=-469 0 xc57f5=0 xfe2b-149776=-235 0 xc57f6=0 xff15-149777=-118 0 xc57f7=0 xff8a-149778=-59
8、 0 xc57f8=0 xffc5-149779=-30 0 xc57f9=0 xffe2-1497710=-15 0 xc57f10=0 xfff1-1497711=-8 0 xc57f11=0 xfff8-1497712=-4 0 xc57f12=0 xfffc-1497713=-2 0 xc57f13=0 xfffe-1497714=-1 0 xc57f14=0 xffff-1497715=-1 0 xc57f15=0 xffff 整数整数-14977-14977的补码是的补码是0 x0 xc57fc57f。整型数据每右移一位相当于数。整型数据每右移一位相当于数据除以据除以2 2,同时还
9、注意到,同时还注意到-1/2=-1-1/2=-1。n n其他位运算其他位运算 除了移位运算,二进制数据的位运算还包括与、或、非、异或四种类型。从数据本身的角度来看,位运算本身的意义不大。但是在跟计算机硬件相关的很多操作中,位运算有其他运算无可比拟的优势。位运算真值表位运位运算符算符运算运算结结果果&0&0=0,0&1=0,1&0=0,1&1=1|0|0=0,0|1=1,1|0=1,1|1=10=1,1=000=0,01=1,10=1,11=0【例例13.3】将数据的最末位置位为将数据的最末位置位为0。1#include 2 void main()3 4 int aValue;5 int i;6
10、 for(i=0;i5;i+)7 8 printf(Please input a integer:);9 scanf(%d,&aValue);10 aValue=aValue&0 xfffe;11 printf(The new value is:%dn,aValue);12 13 运行结果如下:运行结果如下:Please input a integer:19The new value is:18Please input a integer:1221The new value is:1220Please input a integer:12The new value is:12Please in
11、put a integer:17The new value is:16Please input a integer:400The new value is:400【例例13.4】字符串的简单加密字符串的简单加密1#include 2#include 3void main()45char maskChar=0 x55;6char*sourceString=Hello;7char*destString1;8char*destString2;9int i;10destString1=malloc(strlen(sourceString);11destString2=malloc(strlen(sou
12、rceString);12for(i=0;istrlen(sourceString);i+)13destString1i=sourceStringimaskChar;14destString1i=0;15for(i=0;istrlen(sourceString);i+)16destString2i=destString1imaskChar;17destString2i=0;18printf(sourceString=%sn,sourceString);19printf(destString1=%sn,destString1);20printf(destString2=%sn,destStrin
13、g2);21 运行结果如下:运行结果如下:sourceString=HellodestString1=099:destString2=Hello【例13.5】AD574是一种A/D转换器,它的作用就是将模拟信号转换成数字信号。它对外有2个端口,分别叫作偶地址端口和奇地址端口。向偶地址端口发送命令可以启动A/D转换,从偶地址端口读取数据可以获取A/D转换是否完成的状态。在A/D完成后,从偶地址可以获取转换数据的高8位数据,从奇地址可以获取低4位数据。假设根据硬件连接情况,得到端口地址0 x500和0 x501。在C语言的库函数中,有访问外设端口的outportb函数,它将一个字节数据写入外设端口
14、寄存器。inportb函数把端口寄存器中一个字节读入CPU。下面的程序给出了一个数据采集函数。1unsigned ad_convert()23unsigned ad_h8=0;4unsigned ad_L4=0;5unsigned ad_result=0;6outportb(0 x500,0 xff);7while(inportb(0 x500)&0 x80);8ad_h8=(unsigned)inportb(0 x500);9ad_L4=(unsigned)inportb(0 x501);10ad_h8=ad_h84;12ad_result=ad_h8+ad_L4;13return(ad_r
15、esult);14 13.3 位段n我们知道计算机中信息的存储一般是以字节为单位的。实际上,有时一个信息本身可能用不到那么多位。例如,要表示人的性别只需1位二进制数据就可以,譬如0代表“男”,1代表“女”。再例如在过程控制领域,一个字节的数据可以表示多个命令或者设备的多个状态特征。n虽然可以用移位或其他位运算组合成我们需要的信息,但是,C语言提供了更方便的利用位段结位段结构构处理信息的方法。位段:位段:在一个结构体中可以以在一个结构体中可以以位位为单位来指定为单位来指定 其成员所占内存长度,这种以位为单位其成员所占内存长度,这种以位为单位 的成员称为位段(或位域)。的成员称为位段(或位域)。如
16、:如:struct packed_data unsigned a :2;unsigned b:3;unsigned c:4;int i;data;存储单元分配:共存储单元分配:共4个字节个字节 716432a b c i位段的引用:位段的引用:结构体变量名结构体变量名.位段成员名位段成员名 如:如:struct packed_data unsigned a :2;unsigned b:3;unsigned c:4;int i;data;位段的引用如下:位段的引用如下:data.a=2;data.b=7;data.c=9;【例例13.6】定义位段定义位段1typedef struct23unsi
17、gned a:3;4unsigned b:1;5unsigned c:7;6Some_bits;7#include 8void main()910Some_bits theseBits;11unsigned int*pInteger;12pInteger=(unsigned int*)&theseBits;13*pInteger=0;14theseBits.a=6;15theseBits.b=1;16theseBits.c=16;17printf(sizeof(Some_bits)=%dn,sizeof(Some_bits);18printf(*pInteger=%xn,*pInteger);
18、19printf(%u,%u,%un,theseBits.a,theseBits.b,theseBits.c);20 位段的定义位段的定义位段的赋值位段的赋值位段的引用位段的引用运行结果如下:运行结果如下:sizeof(Some_bits)=2*pInteger=10e6,1,16 15 14 13 12 11 109876543210Unusedcba有定义的位段位于整个结构数据的低位。在位段中定义在位段中定义无名字段无名字段含义:含义:跳过该字节剩余的位或指定的位不用。跳过该字节剩余的位或指定的位不用。当无名字长度为当无名字长度为0时,跳过该字节剩余的位不时,跳过该字节剩余的位不用;当无名
19、字段长度为用;当无名字段长度为n时,跳过时,跳过n位不用。位不用。如:如:struct packed_data unsigned a :2;unsigned b:3;unsigned :0;unsigned c:4;int i;data;存储单元分配:共存储单元分配:共4个字节个字节 4343216 a b c i【例例13.7】未命名位段举例。未命名位段举例。1typedef struct23unsigned a:3;4unsigned:2;5unsigned b:1;6unsigned:0;7unsigned c:7;8Unamed_bits;9#include 10 void main(
20、)11 12Unamed_bits theseBits;13unsigned int*pInteger;14pInteger=(unsigned int*)&theseBits;15*pInteger=0;16theseBits.a=6;17theseBits.b=1;18theseBits.c=16;19printf(sizeof(Unamed_bits)=%dn,sizeof(Unamed_bits);20printf(*pInteger=%xn,*pInteger);21printf(%u,%u,%un,theseBits.a,theseBits.b,theseBits.c);22 运行结果如下:运行结果如下:sizeof(Unamed_bits)=2*pInteger=10266,1,1615141312 11 109876543210unusedcunused b unuseda位段结构位段结构