位运算(人民邮电管银枝主篇).ppt

上传人:小飞机 文档编号:6548784 上传时间:2023-11-11 格式:PPT 页数:38 大小:219KB
返回 下载 相关 举报
位运算(人民邮电管银枝主篇).ppt_第1页
第1页 / 共38页
位运算(人民邮电管银枝主篇).ppt_第2页
第2页 / 共38页
位运算(人民邮电管银枝主篇).ppt_第3页
第3页 / 共38页
位运算(人民邮电管银枝主篇).ppt_第4页
第4页 / 共38页
位运算(人民邮电管银枝主篇).ppt_第5页
第5页 / 共38页
点击查看更多>>
资源描述

《位运算(人民邮电管银枝主篇).ppt》由会员分享,可在线阅读,更多相关《位运算(人民邮电管银枝主篇).ppt(38页珍藏版)》请在三一办公上搜索。

1、第十一 位运算,C语言既具有高级语言的特点,也具有低级语言的特点。本节所讲的位运算就具有低级语言的特点,并被广泛用于对底层硬件、外围设备的状态检测和控制。计算机真正执行的是由0和1信号组成的计算机指令,数据也是以二进制形式表示的。因此最终要实现计算机的操作,就要对这些0和1进行操作。每一个0和1的状态称为一个“位”(bit)的状态。有了位运算,C语言就能编写出直接对计算机硬件进行操作的程序。,本章主要内容,11.1 位运算及位运算符概述11.2 位运算11.3 位域11.4 位运算应用举例,11.1位运算及位运算符概述,11.1.1 位运算概述 所谓位运算是指对操作数以二进制位(bit)为单位

2、进行的数据处理。每一个二进制位只能存放1位二进制数“0”或“1”,因此位运算符的运算对象是一个二进制数位的集合。通常把组成一个数据的最右边的二进制位称作第0位,从右向左依次称为第1位,第2位,最左边一位称作最高位。,1112位运算符位的种类,C语言中,位运算包括逻辑位运算和移位位运算。1、逻辑位运算分为四种:位反、位与、位或、位异2、移位位运算分为二种:左移与右移。在c语言中的移位不是循环移动,经过移位后一端的位被“挤掉”,而另一端空出的位补0。,3、位复合赋值运算符类似于算术的复合运算符,位运算符和赋值运算符也可以构成复合赋值运算符。,4、关于位运算符的几点说明(1)在逻辑位运算中,的优先级

3、高于算术运算符、关系运算符、逻辑运算符,其他位运算符则低于关系运算符、高于逻辑运算符。(2)参加位运算的操作数必须是整型或字符型数据(常量或变量),不能是其它类型的数据。(3)两个长度不同的数据进行位运算时,系统先将两者的右端对齐,短的运算对象若是有符号数则按符号位扩展,若是无符号数则以“0”扩充。(4)位运算符的优先级如下:按位取反运算符“”的优先级最高,高于所有的双目运算符;其次是左移运算符“”,其优先级高于关系运算符;最低的是按位与“&”、按位异或“”和按位或“|”运算符,其优先级低于关系运算符。(5)除了按位取反运算符“”的结合方向是自右至左外,其余位运算符的结合方向都是自左至右(6)

4、位运算符和逻辑运算符很相似,要注意区别。关系运算和逻辑运算的结果只能是1或0,而按位运算的结果不一定是1或0,还可以是其它数。,11.2 位运算,任务提出:如何统计一个字符对应的ASCII码中1的个数?任务分析:此问题首先要从键盘输入一个字符,然后统计出该字符对应的ASCLL码值转换成二进制后1的个数。解决此问题的难点在于如何判断该字符对应ASCII码值转换成二进制后每个位上的数字是0还是1。设从键盘输入的字符用ch表示,该问题需对字符ch的ASCII码的每一位进行测试,判断是0还是1。方法是:设置一个屏蔽字与ch进行“&”运算,从而取所需的某位的状态(0或1)。从高位开始,第8位所需设置的屏

5、蔽字mask为0 x80,即二进制10000000,若ch&mask的结果为0,则说明ch的第8位为0,否则为1。第7位所需设置的屏蔽字mask为0 x40,即将mask右移一位。如此一直下去,直到结束。,#include stdio.hmain()char ch;int mask,i,count=0;printf(请输入一个字符:);ch=getchar();printf(该字符的ASCII是%dn,ch);mask=0 x80;for(i=0;i=1;printf(ASCII中1的个数有:%dn,count);getch();,11.2 1 按位取反运算,按位取反运算是用来对二进制按位进行

6、取反运算,是单目运算符。按位取反运算符用“”表示。按位取反运算符是位运算中惟一的单目运算符,运算对象应置于运算符的右边。1、按位取反运算的运算规则按位取反运算的运算规则:把运算对象的内容按位取反,将每一位上的0变1,1变0。即0=1,1=0。例如:对十六进制数32进行取反。0 0 1 1 0 0 1 0=1 1 0 0 1 1 0 1结果为1 1 0 0 1 1 0 1。又如:a=0000 0000 0000 1011,则表达式a的值为1111 1111 1111 0100。unsigned char a,b;/*定义两个无符号字符型变量a,b*b=a/*对变量a全部位取反,结果赋值给b*/p

7、rintf(a=%dn,b);/*输出十进制b值*/,2、按位取反运算的主要应用按位取反运算的主要应用:用来适应不同字长型号的机型,帮助得到使原数最低位为0。例如:想使a中最低位为0,可让a=a&1。如果a 是16位,其中1等于0177776,与a相与后,使最低位为0。如果是a是32位,其中1等于0377776,与a相与后,使最低位为0。总之,不管什么样的机型,只要用a=a&1,就可以使原数的最低位为0,而其余位不变。,11.2.2 按位与运算,按位与运算是指参与运算的两个数对应的二进制位进行逻辑与的操作,用“&”表示。1、按位与运算符的规则按位与运算符的规则:若两个运算对象的对应二进制数位均

8、为1,则结果的对应数位为1,否则为0。按位与运算可能的运算组合及其运算结果如下所示:0&0=0 1&0=0 0&1=0 1&1=1即当两个数对应的位全为1时,得到的该位就为1,只要对应的位有一个0,得到的该位就为0。按位与运算的特点:二进制数的任何数位,只要和数位0进行“与”运算,该位清零;和数位1进行“与”运算,该位保留原值不变。例如,x=0000 0000 0000 1011,y=0000 0000 0000 1010,则表达式x&y的计算结果如下:,2按位与运算的主要应用(1)按位清零:只要把需要进行清零的位与0进行“按位与”操作,其余与1进行“按位与”操作即可。例:把整型变量a的高八位

9、清0,保留低八位。方法是:把a和一个高八位为0,低八位为1的数进行按位与运算。程序清单如下:main()int a=268,b=0 x00ff,c;c=a 运行结果:a=264,b=255,c=13(2)测试指定位的值:要判断某一指定位的值是否为1或0,只需将这一位与1进行“按位与”操作,然后判断结果是否为1或0即可。,例:设x是一个字符型变量(8位二进制位),判断x的最低位是否为1。方法是:把x和0 x01进行“按位与”运算,如果结果为1则x的最低位是1。x=*运行结果:x=268,y=1,z=0应当注意:“按位与”运算&的优先级低于关系运算符!、=和=,所以在判断结果是否为零时,表达式(x

10、&0 x01)!=0中的圆括号不能省略。,(3)获取指定位的值:要想获取某些位的判断某些位的值,只需将这些位的与1进行“按位与”操作,其余与0进行“按位与”操作。比如,设a=00101101,想取出a中的25位,方法是:令a 运行结果:x=268,y=255,z=12,11.2.3 按位或运算,按位或运算符是指参与运算的两个数对应的二进制位进行逻辑或的操作,用“|”表示。1、按位或运算符的运算规则按位或运算符的运算规则:当两个数对应的位全为0时,得到的该位就为0,只要对应的位有一个1,得到的该位就为1。按位或运算可能的运算组合及其运算结果如下所示:0|0=0 1|0=1 0|1=1 1|1=1

11、例如,x=0000 0000 0000 1011,y=0000 0000 0000 1010,则表达式x|y的计算结果如下:结果为十进制11。,2按位或运算的主要应用按位或运算的主要应用:按位置1。只要把需要置1的位与1进行“按位或”的操作,其余与此0进行“按位或”的操作。例:设x是一个整型变量,要求将x的低八位置1。方法是x=*|0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1结果:*1 1 1 1 1 1 1 1最后的结果是将x的低八位置1。程序清单如下:main()int x=268,y=0 x00ff,z;z=x|y;printf(x=%d,y=%d,z=%dn,x,y,

12、z);,11.2.4 按位异或运算,按位异或运算符是指参与运算的两个数对应的二进制位进行逻辑按位异或的操作,用“”表示。1、按位异或运算符的运算规则按位异或运算符的运算规则:若两个运算对象的对应二进制位不同,则结果的对应数位为1,否则为0。按位异或运算可能的运算组合及其运算结果如下所示:00=0 10=1 01=1 11=0 例如,x=0000 0000 0000 1011,y=0000 0000 0000 1010,则表达式xy的计算结果如下:,又如:c=10610:0000,0000,0000,1010&6:0000,0000,0000,0110c:0000,0000,0000,1100(

13、12),2按位异或运算的主要应用按位异或运算的主要应用:特定位翻转和保留原值。(1)特定位翻转方法:特定位与1异或。对某些位进行操作,如该位为1则将它变为0,如该位为0则将它变为1。例如:设a是一个字符型变量,现要求将a的低4位翻转。a=0 1 1 0 0 1 1 0 0 0 0 0 1 1 1 1 结果:0 1 1 0 1 0 0 1最后的结果是将a的低4位翻转。,(2)保留原值方法:与0异或。例如:设a是一个字符型变量,现要求将a的低4位保留原值。a=0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0结果:0 1 1 0 0 1 1 0最后的结果是将a的低4位保留原值。(3)不

14、用临时变量,实现交换两个变量的值。,例:将一个整数的低4位,如果是1变为0,如果是变为1。#include stdio.hmain()int a,b=0 xf,c;printf(请输入一个十六进制数a:n);scanf(%x,11.2.5 左移运算,左移运算符是把“”符号左边的运算数的各二进制位全部左移若干位,移动的若干位由“”符号右边的数指定,高位丢弃,低位补0,用“”表示。1、左移运算符的运算规则左移运算符的运算规则:将运算对象中的每个二进制数位向左移动若干位,从左边移出去的高位部分被丢弃,右边空出的低位部分用“0”补齐。例如:x=0000 0000 0000 1011,则x2的结果为00

15、00 0000 0010 1100。又例如:左移运算举例:char a=30;a=a2;结果如下:(30)=(0001,1110)(二进制)左移后为(120)=(0111,1000)(二进制),注意:若移出的高位部分不包含数位1,则每左移1位,相当于乖2,左移n 位相当于乖2的n次方。若对c=44(00101100)进行下面的操作:c=c1;c的值变为88(01011000)c=c1;c的值变为176(10110000),11.2.6 右移运算,右移运算符把运算符左边的运算数的各二进制位全部右移若干位,用“”表示,移动的若干位由“”符号右边的数指定。右移运算符的运算规则:将运算对象中的每个二进

16、制数位向右移动若干位,从右边移出去的低位部分被丢弃,左边空出的高位部分的处理分两种情况。对无符号数和正数来讲,左边空出的高位部分补“0”;对负数来讲,左边空出的高位部分补“0”还是补“1”,与所使用的编译程序有关,有的编译程序补“0”,称为逻辑右移,有的编译程序补“1”,称为算术右移。例如:char a=0 x78;a=a2;结果如下:16进制78=120=(0111,1000)(二进制)右移后为:(30)=(0001,1110)(二进制),应当注意:(1)若移出的位全为0,则每右移1位,相当于除2,右移n 位相当于除2的n次方。(2)当进行右移运算时,操作结果与操作数是否带符号有关。v无符号

17、操作数右移时,左端出现的空位补0,右端移出的数据舍去。v带符号操作数右移时,左端出现的空位补符号位。若符号位为0则左边也是移入0,若符号位为1则左端也是移入1,移出的数据舍去。例如:带符号数a=16和无符号数b=240,进行下列操作:a=a1;a的值变为8(11111000)b=b1;b的值变为120(01111000)a=a1;a的值变为4(11111100)b=b1;b的值变为60(00111100),11.3 位域,在程序设计中,有时存储一个信息不必用一个或多个字节,可以在一个字节中存放一个或多个信息。例如,“真”或“假”用1或0表示,只需一位即可,如果用一个变量来存储,则将浪费存储空间

18、。为了解决该问题,C语言提供了位段操作。在前面介绍的位与运算、位或运算、位异或运算、反运算、左移运算、右移运算等几种的综合运算,可以实现对某一位或某几位的存取,但较麻烦。c语言中允许在结构体中以位为单位来指定其成员所占的内存长度,这种以位为单位的成员就称为位段或位域(bit field)。所谓位段是由一个或多个二进制数位组成的,它是数据的一种压缩形式。位段是一种特殊的压缩形式结构体结构中的成员,它的特殊性在于它是以位为单位定义长度的。,11.3.1 位域或位段(bit field)的定义形式,c语言中允许在结构体中以位为单位来指定其成员所占的内存长度,这种以位为单位的成员就称为位段或位域(bi

19、t field)。所谓位段是由一个或多个二进制数位组成的,它是数据的一种压缩形式。位段是一种特殊的压缩形式结构体结构中的成员,它的特殊性在于它是以位为单位定义长度的。,11.3.1 位域或位段(bit field)的定义形式,位域或位段(bit field)的定义形式如下:struct 位域结构体名位域列表其中,位域列表的形式为:类型说明符 位域名:位域长度;其中,位域名的类型必须指定为unsigned int 型或int型,一般为unsigned型。位域长度以二进制位为单位。例如:struct bs unsigned int a:1;unsigned int b:3;unsigned int

20、 c:4;bit,*pbit;定义了结构体bs,该结构体变量共有3个成员,其中a,b,c成员是位段,分别占1位、3位、4位,共占1个字节。,又如:struct wd unsigned a:2;unsigned b:3;unsigned c:6;unsigned d:4;int k;dat;定义了结构体wd,该结构体变量共有5个成员,其中a、b、c、d成员是位段,分别占2位、3位、6位、4位,k是的一般成员,k占2个字节。,11.3.2 位域的引用,位域的引用方法与引用结构体变量中的成员相同,即:位域结构体名.位域名在C语言中,可以通过赋值语句给位域赋值。例如:struct bs unsined

21、 a:6;int b:2;int c:8;data;这里定义一个位域结构bs,同时定义了data为bs变量,共占两个字节。其中位域a占6位,b占2位,c占8位。位域中数据的引用为:data.a=7;data.b=1;data.c=9;,注意:,1、赋值时不能超过位域允许的最大值范围,如data.b 只占2个位,最大值为3,此时若把8(二进制为1000)赋给它,就会自动取赋予该数的低位,也是就00,最终data.b的值为0。2、位域还可以用整型格式符输出。例如:printf(“%d,%d,%dn”,data.a,data.b,data.c);也可以用%u、%o、%x等格式符输出。,11.4 位运

22、算应用举例,例:从键盘上输入一个正整数n,判断此数是奇数还是偶数。分析:奇数的二进制表示中右边的第1位为1,偶数的二进制表示中右边的第1位为0。因此该题就转换为取该数右边的第1位,并判断其值是否为0。程序清单如下:main()int n;printf(请输入一个大于0的数 n:);scanf(%d,例:将十六进制数转换为二进制数。,分析:人们有时希望知道某个十六进制数的二进制数是什么,但C语言的printf()函数只提供%x,%d,%o方式输出一个整数(即十六进制,十进制,八进制)而不能直接输出一个整数的二进制形式,需要人工转换,很不方便。在这里可以用位运算来实现此功能。采用的方法是:对一个整

23、数num(16位)的每一位进行测试,视其为0还是为1,可以设置一个屏蔽字与该数进行 该bit的值(非1即0)就是num第15位之值。下面处理第14位,此时mask应改为0 x4000,也就是使mask右移一位。,main()int j,num,bit;unsigned int mask;mask=0 x8000;printf(n请输入一个数十六进制的数:);scanf(%x,本章小结,C语言是为了描述系统而设计的,它既具有高级语言的特点,又具有低级语言的功能。位运算就是其低级语言的功能,本章介绍了位运算和位域。1、位运算 所谓位运算是指对二进制数位进行的运算。每一个二进制数位只能存放0或1,因此位运算符的运算对象是一个二进制数位的集合。本章介绍了C语言提供的六种位运算符(按位与&、按位或|、按位异或、按位取反、左移)的格式、运算规则、主要用途及实现方法。2、位域 位域是一种比较简单的结构体,它以位为单位来指定其成员所占内存的长度,这种以位为单位的成员构成的结构称为“位域”或称为“位段”。本章介绍了位域的概念、定义及引用方法。,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号