c语言从入门到精通--第16章课件.ppt

上传人(卖家):晟晟文业 文档编号:5217959 上传时间:2023-02-17 格式:PPT 页数:56 大小:170.21KB
下载 相关 举报
c语言从入门到精通--第16章课件.ppt_第1页
第1页 / 共56页
c语言从入门到精通--第16章课件.ppt_第2页
第2页 / 共56页
c语言从入门到精通--第16章课件.ppt_第3页
第3页 / 共56页
c语言从入门到精通--第16章课件.ppt_第4页
第4页 / 共56页
c语言从入门到精通--第16章课件.ppt_第5页
第5页 / 共56页
点击查看更多>>
资源描述

1、第16章合理利用内存位运算p 二进制数 p 位运算符 p 位域 p 综合应用数制转换 p 跟我上机 第16章C合理利用内存位运算 二进制数 p 位运算符 p 位域 p 综合应用数制转换 p 跟我上机 第16章C合理利用内存位运算 二进制数 位运算符 p 位域 p 综合应用数制转换 p 跟我上机 第16章C合理利用内存位运算 二进制数 位运算符 位域 p 综合应用数制转换 p 跟我上机 第16章C合理利用内存位运算 二进制数 位运算符 位域 综合应用数制转换 p 跟我上机 第16章C合理利用内存位运算 二进制数 位运算符 位域 综合应用数制转换 跟我上机 C合理利用内存位运算数据在计算机里是以二

2、进制形式表示的,在实际程序中,许多系统程序需要直接对二进制位数据操作,还有不少硬件设备与计算机通信都是通过一组二进制数控制和反应硬件的状态。C语言特别提供了直接对二进制位的操作的功能,称为位运算。位运算直接对内存中二进制数据进行操作,无需转成十进制,因此处理速度非常快。位运算的正确使用,可以合理利用内存,优化程序。16.1 二进制数16.1.1 二进制16.1.2 无符号数和有符号数16.1.1 二进制二进制就是逢二进一,比如十进制数3转换为二进制数11,十进制数10转换为二进制数1010。要把二进制数转换为十进制数,可以使用二进制的数字每一位对应一个2的某次幂,然后累加求和。比如:(1011

3、)2=1*23+0*22+1*21+1*20=8+0+2+1=(11)1032323216.1.1 二进制把二进制数中的每一个二进制数称为位(bit,比特),即,每个0或1就是一个位),位是数据存储的最小单位。通常,把一组4位二进制数称为半字节(nibble),一组8位二进制数称为一个字节(byte)。通常把两个或者四个字节称为一个字(word),两个字又称之为一个双字(double word)。16.1.2 无符号数和有符号数对一个字节而言,八位二进制数都是用来存储数据的,它只能表示非负整数,范围为0255。二进制0000 0000最小,表示十进制的0;二进制 1111 1111最大,表示十

4、进制的255。有符号数是通过一个字节左边第一位的二进制数来表示,0时表示整数,1表示负数。比如1000 0011表示-3,0000 0011表示3。16.1.2 无符号数和有符号数问题看似很完美地解决了,再来看个特殊情况,就是十进制数0。使用0000 0000 表示正0,使用1000 0000 表示负0,这样一对多的关系不利于数据的存储,程序开发也会产生很多隐患。为了解决以上问题,引入了二进制补码机制。正数的时候最高位是0,不需要再求补码(数在计算机内部存储时用来表示的二进制数),或者可以理解为原码(数直接转换的二进制数)和补码是相同的,因此0000 0011表示为十进制3。16.1.2 无符

5、号数和有符号数 负数的时候最高位是1,表示的原码先按位取反后加1(符号位不动),比如-3的原码是1000 0011,先按位取反变为1111 1100,然后再加1变成1111 1101,这样1111 1101就是-3在计算机内部存储时用来表示它的二进制数。反之,当你知道存储器中有序列1111 1101,而且知道它的最高位是符号位,表示的是一个负整数,把把转变为十进制数的方法就是先减1(符号位不动),变为1111 1100,然后再按位取反得1000 0011,即它表示的就是是-3了。注意:在这种系统中+0就是0000 0000,而此时的1000 0000则表示-128(这个特殊,不遵循补码机制,硬

6、性规定)。16.2 位运算符16.2.1 按位与运算符16.2.2 按位或运算符16.2.3 按位异或运算符16.2.4 按位取反运算符16.2.5 左移运算符16.2.6 右移运算符16.2.7 位运算赋值运算符16.2.8 位运算应用16.2 位运算符位运算符描述&按位与|按位或按位异或取反右移16.2 位运算符说明:位运算符中除以外,均为双目(元)运算符,即要求两侧各有一个运算量。运算量只能是整型或字符型的数据,不能为实型数据。16.2.1 按位与运算符按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1,否则为0,即:0

7、00,0 10,1 00,1 11注意:参与运算的数以补码形式出现。16.2.1 按位与运算符1.正数的按位与运算例如:计算10&5,需要先把十进制数转换为补码形式,再按位与运算,计算如下。0000 1010 10的二进制补码&0000 0101 5的二进制补码0000 0000 按位与运算,结果转换为十进制后为0所以10&5=016.2.1 按位与运算符2.负数的按位与运算例如:计算-9&-5。第1步:先转换为补码形式。-9的原码:1000 1001,反码:1111 0110,补码:1111 0111-5的原码:1000 0101,反码:1111 1010,补码:1111 1011第2步:补

8、码进行位与运算。1111 0111-9的二进制补码&1111 1011-5的二进制补码1111 0011按位与运算第3步:将结果转换为原码。补码:1111 0011,反码:1111 0010,原码:1000 1101,原码:-13,所以-9&-5=-13 16.2.1 按位与运算符3.按位与的作用按位与运算通常用来对某些位清0或保留某些位。例如要求把a 的高八位清 0,保留低八位,可以使用 a&255 运算(255 的二进制数为0000000011111111)。又比如,有一个数是0110 1101,希望保留从右边开始第3、4位,以到达程序的某些要求,可以这样运算:0110 1101&0000

9、 11000000 1100上式描述的就是为了保留指定位,进行的按位与运算,如果写成十进制形式,可以写成表达式如下109&12。16.2.2 按位或运算符按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1,即:0|00,0|11,1|01,1|11参与运算的两个数均以补码出现。例如:10|5可写算式如下:0000 1010|0000 01010000 111115的二进制补码所以10|5=1316.2.2 按位或运算符常用来将源操作数某些位置1,其它位不变。首先设置一个二进制掩码mask,执行 s=s|mask,把其中特定位

10、置1,其它位为0。比如有一个数是0000 0011,希望把它从右边开始第3、4位置为1,其他位不变,可以写成如下的形式:0000 0011|0000 1100=0000 1111即3|12=1516.2.3 按位异或运算符按位异或运算符“”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1,即:0 0=0,0 1=1,1 0=1,1 1=0参与运算数仍以补码出现,例如10 5可写成算式如下:0000 10100000 01010000 111115的二进制补码所以10 5=15充分利用按位异或的特性,可以实现以下效果。16.2.3 按位异或运算符 设置一

11、个二进制掩码mask,执行s=s mask,设置特定位置是1,可以使特定位的值取反;设置掩码中特定位置其它位为是0,可以保留原值。设有0111 1010,想使其低4位翻转,即1变为0,0变为1。可以将它与0000 1111进行运算,即:0111 1010 0000 11110111 010116.2.3 按位异或运算符 不引入第三变量,交换两个变量的值。想将a和b的值互换,可以用以下赋值语句实现:a a b;b b a;a a b;分析如下:(按位异或满足交换率)a=a b;b=b a=b a b=b b a=0 a=a;a=a b=a b a=a a b=0 b=b;假设a=3;b=4;验证

12、如下:a011b100a111(a b的结果,a变成)b100b011(b a的结果,b变成3)a11116.2.4 按位取反运算符求反运算符“”为单目运算符,具有右结合性。其功能是对参与运算的数的各二进位按位求反。例如9的运算为:(0000 1001),结果为:(1111 0110),如果表示无符号数是246,如果表示有符号数是-10(按照上文的方法自己演算)。16.2.5 左移运算符左移运算符“”是双目运算符。其功能把“”左边的运算数的各二进位全部左移若干位,由“”右边的数指定移动的位数。1.无符号数的左移如果是无符号数,则向左移动n位时,丢弃左边n位数据,并在右边填充0。如下图所示。16

13、.2.5 左移运算符十进制n=1:00000001n1,十进制2:00000010n1,十进制4:00000100n1,十进制8:00001000n1,十进制16:00010000n1,十进制32:00100000n1,十进制64:01000000n1,十进制128:1000000016.2.5 左移运算符程序到这里还都是很正常的,每次左移一位,结果是以2的幂次方不断变化,此时继续左移,产生如下的结果。n1,十进制0:0000000016.2.5 左移运算符2.有符号数的左移如果是有符号数,则向左移动n位时,丢弃左边n位数据,并在右边填充0,同时把最高位作为符号位。这种情况对于正数,跟上述的无

14、符号数左移结果是一样的,不再分析,那对于负数呢,如下图所示。16.2.5 左移运算符十进制n=-128:10000001n1,十进制2:00000010n1,十进制4:00000100n1,十进制8:00001000n1,十进制16:00010000n1,十进制32:00100000n1,十进制64:01000000n1,十进制128:10000000n1,十进制0:00000000n”是双目运算符。其功能是把“”左边的运算数的各二进位全部右移若干位,“”右边的数指定移动的位数。1.无符号数的右移如果是无符号数,则向右移动n位时,丢弃右边n位数据,并在左边填充0。如下图所示。16.2.6 右移

15、运算符十进制n=128:10000000n1,十进制64:01000000n1,十进制32:00100000n1,十进制16:00010000n1,十进制8:00001000n1,十进制4:00000100n1,十进制2:00000010n1,十进制1:0000000116.2.6 右移运算符程序到这里还都是很正常的,每次右移一位,结果是以2的幂次方不断变化,此时继续右移。结果变成了0,显然结果是不对的,所以右移时一旦溢出就不再正确了。在不溢出的情况下,右移一位相当于除以2,右移n位相当于除以2n。n1,十进制0:0000000016.2.6 右移运算符2.右符号数的右移如果是有符号数,则向右

16、移动n位时,丢弃右边n位数据,而左边填充的内容依赖于具体的机器,可能是1也可能是0。比如对于有符号数(1000 1010)来说,右移有两种情况:(1000 1010)2=(00 10 0010);(1000 1010)2=(11 10 0010);16.2.6 右移运算符十进制n=-64:11000000n1,十进制-32:11100000n1,十进制-16:11110000n1,十进制-8:11111000n1,十进制-4:11111100n1,十进制-2:11111110n1,十进制-1:11111111n1,十进制-1:1111111116.2.6 右移运算符最高的符号位保持原来符号位不

17、断右移,直到全部变成1。在不溢出的情况下,右移一位相当于除以2,右移n位相当于除以2的n次幂。16.2.6 右移运算符提提 示示:这样左端填1来处理有符号数右移的情况,就是所谓的“算术右移”,如果右移时左端统统填0,则称之为“逻辑右移”。16.2.7 位运算赋值运算符位运算赋值运算符位运算赋值运算符举例举例等价于等价于&=a&=ba=a&b|=a|=ba=a|b=a=ba=a b=a=2a=a 2=2a=a 216.2.8 位运算应用【范例16-1】分析以下程序的位运算的结果。01#include 02 int main()03 04 unsigned char a,b,c;/*声明字符型变量

18、*/05 a=0 x3;/*a是十六进制数*/06 b=a|0 x8;/*按位或*/07 c=b1;/*左移运算*/08 printf(%dn%dn,b,c);09 return 0;10 16.2.8 位运算应用变量a的二进制数:000000110 x8的二进制数:00001000变量b的二进制数:0000 0011|0000 10000000 1011十进制11的二进制码变量b左移1位,结果是:00010110所以变量c的值是十进制22。16.2.8 位运算应用【范例16-2】取一个整数a从右端开始的47位并输出 01#include 02 int main()03 04 unsigned

19、 short a,b,c,d;/*声明字符型变量*/05 scanf(%o,&a);06 b=a4;/*右移运算*/07 c=(04);/*取反左移后再取反*/08 d=b&c;/*按位与*/09 printf(%on%on,a,d);10 return 0;11 16.2.8 位运算应用此范例分三步进行:先使a右移4位;然后设置一个低4位全为1,其余全为0的数,可用(04);最后将上面二者进行&运算。输入的八进制数是1640,转换为2进制数是:0000 0011 1010 0000,获取其右端开始的4到7位是二进制数1010,转换为八进制就是12。15830741543016.2.8 位运算

20、应用【范例16-3】将无符号数a右循环移n位,即将a中原来左面(16-n)位右移n位,原来右端n位移到最左面n位。01#include 02 int main()03 04 unsigned short a,b,c;/*声明字符型变量*/05 int n;06 scanf(%o,%d,&a,&n);/*输入八进制和十进制数*/07 b=an;/*右移运算*/09 c=c|b;/*按位或*/10 printf(%on%on,a,c);/*输出八进制数*/11 return 0;12 16.2.8 位运算应用题目分三步进行:将a的右端n位先放到b中的高n位中,实现语句:ban;最后c与b进行按位或

21、运算,即cc|b。题目中输入的八进制数是1641,转换为2进制数是:0000 0011 1010 0001,获取其循环移三位,结果是:0010 0000 0111 0100,转换为八进制就是20164。n位n位a:c:16.3 位域C语言可以在一个结构体中以二进制位为单位来指定其成员所占内存长度,这种以位为单位的成员就称为位域(bit field)。如何以位作为单位来访问数据呢?这样可以更高效的使用存储空间,方法就是使用位域,这样就可以在一个字节中分别存放多个的信息。16.3 位域struct data/*定义结构体*/unsigned n1:6;/*n1占6个位*/unsigned n2:4

22、;/*n2占4个位*/unsigned n3:4;/*n3占4个位*/unsigned n4:2;/*n4占2个位*/mydata;n1n2n3n4 16.3 位域在使用位域时,需要注意以下情况:一个位域必须存储在同一个存储单元中,不能跨两个单元。可以闲置没有使用的存储单元,但是对那种一个剩余存储单元放不下的,就从下一个单元开始存放。而且定义的每一个位域长度不能超过你存储单元。比如你有一个字节去使用,总共8位,你却申请了一个位域是9位的,这就是错误的。16.3 位域 位域名缺省时称作无名位域。例如:struct date/*定义结构体*/unsigned a:2;/*a占2个位*/unsign

23、ed :2;/*空2个位*/unsigned b:1;/*b占1个位*/mydate;第二次申请的2个空间的位域,是闲置不适用的,因为没有位域名称。需要注意的是,同样是无名的位域,它的存储空间是0,有特殊的含义,它指的是这个字节剩余的不再使用,从下个新字节开始存储。例如:struct date/*定义结构体*/unsigned a:2;/*a占2个位*/unsigned :0;/*从下一个新字节开始存储*/unsigned b:1;/*b占1个位*/mydate;16.3 位域 一个结构体中既可以定义位域成员也可以同时定义一般的结构体成员。例如:struct date/*定义结构体*/unsi

24、gned a:2/*a占2个位*/unsigned b:1;/*b占1个位*/int k;/*int类型变量*/mydata;16.3 位域 不能定义以位域结构为元素的数组。关于位域的引用与结构体相同。例如:mydata.a=2;/*赋值*/mydata.b=1;/*赋值*/需要注意的是,a只占两位,在上结构体中有声明,也就是说a最大存储的二进制数是11,转换为十进制就是3,如果写成:mydata.a=10;这并不错,但是结果就不是期望的10了,变成了2,因为10的二进制码是1010,只截取右边两位 10,故结果是2。16.3 位域 位域也可以参与算术表达式的运算,这时系统自动将其转化为整型数。位域可以用整型格式符输出。例如:printf(“%dn”,mydata.a);/*a以有符号整数形式输出*/printf(“%un”,mydata.a);/*a以无符号整数形式输出*/16.4 综合应用数制转换【范例16-4】从键盘上输入一个十进制正整数,按二进制位输出该数。16.6 跟我上机1.编写C程序,将无符号数a左循环移n位,即将a中原来左面n位左移n位,位移到最右面n位。16.6 跟我上机2.编写C程序,将十六进制数转换成二进制。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(c语言从入门到精通--第16章课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|