《c语言设计(第二版)教学.ppt》由会员分享,可在线阅读,更多相关《c语言设计(第二版)教学.ppt(22页珍藏版)》请在三一办公上搜索。
1、c语言设计(第二版)-教学课件,制作人:黄 荧制作人单位:河师大数学与信息科学学院,第十二章 位运算(按位运算),几种关于二进制的按位运算:1 按位与、按位或2 异或、取反3 左移、右移4 位段,00000011&)00000101 00000001,00110000|)00001111 00111111,按位运算的用途:,用位运算可以实现一个字节存放多个数据!,1 按位运算主要在编写系统软件和应用软件中使用2 按位运算能实现在一个字节中存储多个标志性数据 如,一个取值为0,1的标志变量只需要1个数位;存放黑白两色也只需要1个数位.即使存放8种颜色也仅只需要3个数位.3 利用按位运算可以非常方
2、便的从一个字节中读取和写入一个或几个数位上的数据.,12.1 位运算符和位运算(位:指的是二进制的位!),C语言提供的六种位运算:,说明:1)除了取反运算以外,都是二元运算。2)运算量只能是整型或字符型数据,不能是实型数据。,12.1.1 按位与运算符(&)(特别注意:&与&的区别),运算规则:0&0=0,0&1=0,1&0=0,1&1=1,如:3&5=?(3)补=00000011&(5)补=00000101 00000001 3&5=1,练习2-10&7=?(-10)补=11110110&(7)补=00000111 00000110 即,-10&7=6,思考:两个非零数的按位与运算结果可能为
3、0吗?你能举出一个例子吗?,练习1 10&7=?(10)补=00001010&(7)补=00000111 00000010 即,10&7=2,练习3 10&-10=?(10)补=00001010&(-10)补=11110110 00000010 即,10&-10=2,按位与运算的3个常用的特殊用途:,1)清零处理:a=a&02)取一个数的某些位:设a为占2个字节的无符号数,(a)若取a的高8位 c=a&(1111 1111 0000 0000)2=a&(01777400)8(b)取a的低8位:c=a&(0000 0000 1111 1111)2=a&(0377)83)保留一个数的某些位(其他位
4、 置0):如,若保留a的从右数第3,4,5,7,8位 a=a&(0000 0000 1101 1100)2=a&(0334)8,12.1.2 按位或运算符(|)(注意:|与|的区别),运算规则:0|0=0,0|1=1,1|0=1,1|1=1,如:求060|017=?00110000|)00001111 00111111即,060|017=077,按位或的一个常用的特殊用途:将某些数位上的值置为1:如:1)将a的低4位置1,高4位不变 作:a=a|(0000 1111)2=a|(017)82)将a的高4位置1,低4位不变:作:a=a|(1111 0000)2=a|(0360)8,12.1.3 异
5、或运算符(),运算规则:00=0,01=1,10=1,11=0即,相同取0,相异取1,如:071052=?00111001)00101010 00010011071052=023,异或运算的3个特殊应用:与1作异或,使特定位翻转:如:将a的低四位翻转:a=a(00001111)2=a017与0作异或,保留原值 a0=a交换a,b的值,不用临时变量要交换a,b的值,用下列3个赋值语句即可:a=ab;b=ba;a=ab b=b(ab)=abb=a0=a类似地:a=(ab)(b(ab)=aabbb=00b=b,用”按位与”在某些位上做清零,用”按位或”在某些位上做置1,用”异或”在某些位上做翻转!,
6、12.1.4“取反”运算符(),(一元运算)运算规则:0=1,1=0如:求025,其中025为整型数占2个字节。025=(0000 0000 0001 0101)2=(1111 1111 1110 1010)2=0177752特别注意:取反的值是与其所占字节数相关的!,取反运算的一个特殊应用:将一个数的最低位置零。当整数为16位:a&(1111 1111 1111 1110)2=a&0177776而当整数为32位:a&(1111 1110)2=a&037777777776 二者可以统一如下表示:a=a&1 15个1因为当系统为16位时,1=1110 31个1因为当系统为32位时,1=1110,
7、12.1.5 左移运算符(),an功能:将a的二进制数位依次左移n位,右边补零如:a=15,a=a1;15=(00001111)2151=(00011110)2=036=30类似的:a=15,a=a2;152=(00111100)2=074=60但是:a=128,a=a1;128=(10000000)21281=(00000000)2=0(出现溢出!)很容易看出,当无溢出时:a1a*2 an a*2n,12.1.6 右移运算符(),an作用:将a的各二进制数位依次右移n位,左边补0或补1。无符号数:左补0有符号数:a=0:左补0 a0:逻辑右移:左补0 算术右移:左补1 Turbo C采用的是
8、算术右移。,如,1)a=017 a2=(0000 1111)2 2=(0000 0011)2=032)a=-7 a2=(11111001)2 2=(11111110)2(补)=-2另外:与左移类似 a1a/2(整除)ana/2n(整除)但注意到负数的舍入方向与正数不同,-7/2=-4向远离0的方向舍入。,位运算赋值运算符,&,|,b a=b,不同长度的数据进行按位运算,不同长度的数据进行按位运算,效果可能不同:如:long a=2;int b=2;a=a;b=b;所得到的结果是不同的。,12.2 位运算举例,例12.1 取一个整数a从右端开始的47位。(注意到,内存中的最低位是0位。),方法1
9、:(最简单的方法)右移4位,将所取位移至最低位:b=a4;取出最低4位:c=b,方法2:将方法1的017用反运算表示。构造017的要点是:用反运算构造一个高位为0,低4位为1的数。a)从0开始,0=00000(可16位,也可32位)b)取反:0=11111(可16位,也可32位)c)左移4位使低4位为0(可一般化为n):04;c=(04);d=b,例12.1 取一个整数a从右端开始的47位。(程序),#include void main()unsigned a,b,c,d;scanf(%o,方法2:b=a4;c=(04);d=b,考虑:一般地,从右面的第m位开始取其右边的n位?,作:1)b=a
10、(m-n+1);(将第m位开始的n位移至最低位)2)c=(0n);(构造低n位为1,高位为0的数)3)a=b(利用按位与运算取出这n位),例12.2 右循环位移。,即:将a各数位依次右移且将最低位上的溢出位放入最高位。如:右循环位移1位.,右循环位移n位.,处理方法:取出a中低n位放在b中高n位保存:b=an(a为无符号数)将b与c作按位或即得所求:c=c|b,例12.2 右循环位移。(程序),#include void main()unsigned a,b,c;int n;printf(Enter unsigned a,int n:n);scanf(%o%d,右循环位移方法:取出a中低n位放
11、在b中高n位保存:b=an将b与c作按位或即得所求:c=c|b,12.3 位段(位域),位段是为了使一个字节中的数位的读取更为方便直观而设置的.位段是结构体中特殊的成员,它们是以数位来定义长度的,而不是以字节。,如,struct packed_data unsigned a:2;/*成员a为一个占2个二进制数位的位段。*/unsigned b:6;/*b,c,d也为位段*/unsigned c:4;unsigned d:4;int i;data;,(共4个字节),位段的引用,对段位可以象一般整型变量要样给它赋值,但需要注意的是:不要超出它的取值范围。如:struct packed_data u
12、nsigned a:2;unsigned b:3;unsigned c:4;int i;data;dataa=3;dataa=6;因为a仅占2个二进制数位,最大存储的数值为3。(溢出错误),例 各位段长度之和可以不为整字节。,如,struct packed_data unsigned a:2;unsigned b:3;unsigned c:4;int i;data;,(共4个字节),位段的定义和引用 的几点说明:(1-7),1)位段成员的类型必须指定为unsigned或int类型。2)若某一位段要从另一个字开始,可以利用长度为0的位段来实现(规定)。,如:unsigned a:1;unsign
13、ed b:2;unsigned:0;unsigned c:3;,3)一个位段必须存储在同一个存储单元(一个字,不是字节)中,不能跨两个存储单元。,如:unsigned a:12;unsigned b:14;,4)可以定义无名位段。,5)位段的长度不能大于一个字,也不能定义位段数组。6)可以用整型格式符输出 如,用%d,%o,%x,%u等格式输出7)可以用于表达式中,它会被系统自动转化为整型的。,如:unsigned a:1;unsigned:2;/*这两位不用*/unsigned b:3;,00111001)00101010 00010011,)00010101 11101010,00000011&)00000101 00000001,