资源预览内容
第1页 / 共29页
第2页 / 共29页
第3页 / 共29页
第4页 / 共29页
第5页 / 共29页
第6页 / 共29页
第7页 / 共29页
第8页 / 共29页
第9页 / 共29页
第10页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第第11章章 位运算位运算 本章概述 本章的学习目标主要内容1本章概述本章概述lC语言有一个重要特点就是可以直接对二进制位语言有一个重要特点就是可以直接对二进制位进行操作,即位运算。进行操作,即位运算。l二进制位简称位(二进制位简称位(bit),其值为),其值为0或或1。计算机真。计算机真正执行的正是由正执行的正是由0和和1构成的机器指令,计算机内构成的机器指令,计算机内数据也是由二进制表示的。数据也是由二进制表示的。 l数在计算机内均是以补码的形式存储的数在计算机内均是以补码的形式存储的 。l本章介绍位运算和位段结构的有关知识。本章介绍位运算和位段结构的有关知识。2本章的学习目标本章的学习目标l本章教学目的:理解位运算的概念,本章教学目的:理解位运算的概念,掌握基本位运算运算符的使用,理解掌握基本位运算运算符的使用,理解位段的概念。位段的概念。l本章教学重点:基本位运算运算符的本章教学重点:基本位运算运算符的使用使用l本章教学难点:位段的概念本章教学难点:位段的概念3主要内容主要内容11.1 位运算符位运算符 11.2 位运算位运算 11.3 位运算应用举例位运算应用举例 11.4 位段结构位段结构 411.1 位运算符位运算符位运算符位运算符功能功能举举例例按位取反按位取反a:对变对变量量a的全部位取反的全部位取反左移左移 a右移右移 a2:将:将变变量量a的各位全部右移的各位全部右移2位,位,对对于于无符号数和正整数,高位无符号数和正整数,高位补补0;对对于于负负整数,整数,高位高位补补1(适用于(适用于turboc系系统统)&按位与按位与 a&b:对对a与与b的各的各对应对应位位进进行行“按位与按位与”运算运算|按位或按位或 a|b:对对a与与b的各的各对应对应位位进进行行“按位或按位或”运算运算按位异或按位异或 ab:对对a与与b的各的各对应对应位位进进行行“按位异或按位异或”运算运算511.2 11.2 位运算位运算 取反运算取反运算“”是一个单目运算符,运算量在运是一个单目运算符,运算量在运算符之后,取反运算的功能是将一个数据中所有位都算符之后,取反运算的功能是将一个数据中所有位都取其相反值,即取其相反值,即1变变0,0变变1。 运算规则为:运算规则为: 1=0 0=1例例11.1 对于无符号的字符型数据对于无符号的字符型数据a=(18)10 =(00010010)2 ,则则a等于等于(11101101)2 ,即,即(237)10C程序如下:程序如下:11.2.1 按位取反运算按位取反运算6# include int main() unsigned char a=18,b; b=a; printf(“a=%d”,b); return 0; 运行结果为:运行结果为: a= 237 注注意意以以下下程程序序与与左左面面程程序序及及运行结果的区别:运行结果的区别: # include int main() char a=18,b; b=a; printf(“a=%d”,b); return 0;运行结果:运行结果:-19 前一个程序结果很好理解,后一个因为前一个程序结果很好理解,后一个因为a是带符号数据,因是带符号数据,因此此a=(11101101)2的结果是一负数的补码,转换为原码时,第的结果是一负数的补码,转换为原码时,第1位位符号位不变,对剩余的部分先减符号位不变,对剩余的部分先减1,再全部取反,因此得到的二,再全部取反,因此得到的二进制原码为:进制原码为:10010011,即十进制的,即十进制的-19。 711.2 11.2 位运算位运算11.2.2 左移运算左移运算 左左移移运运算算“”是是一一个个双双目目运运算算符符,左左移移运运算算的的功功能能是是将将一一个个数数据据所所有有位位向向左左移移若若干干位位,左左边边(高高位位)移出的部分舍去,右边(低位)自动补零。移出的部分舍去,右边(低位)自动补零。 例例11.2 对于无符号字符型数据对于无符号字符型数据 a=(18)10 =(00010010)2 , a 3的结果是的结果是(10010000)2 ,即(,即(144)108C程序如下:程序如下: # include int main() unsigned char a=18, b; b=a3; printf(“a3=%d”,b); 运行结果为:运行结果为: a3=144注意以下程序与左面程序的区别:注意以下程序与左面程序的区别: # include int main()char a=18,b; b=a3; printf(“a3=%d”,b); return 0; 运行结果为:运行结果为: a3=-112 原原因因同同前前,对对于于带带符符号号数数a,因因a”是是一一个个双双目目运运算算符符,右右移移运运算算的的功功能能是是将将一一个个数数据据所所有有位位向向右右移移若若干干位位,右右边边(低低位位)移移出出的的部部分分舍舍去去,左左边边(高高位位)移移入入的的二二进进制制数数分分两两种种情情况况:对对于于无无符符号号数数和和正正整整数数,高高位位补补0;对对于于负负整整数数,高高位位补补1(适用于适用于turboc系统系统)。)。 例例11.3 对于无符号字符型数据对于无符号字符型数据 a=(18)10 =(00010010)2 , 则则 a 3的结果是的结果是(00000010)2,即(,即(2)1010C程序:程序: # include int main() unsigned char a=18, b; b=a3; printf(“a3=%d”,b); return 0;运行结果为:运行结果为: a3=21111.2 11.2 位运算位运算11.2.4 按位与运算按位与运算 按位按位“与与”运算符要求有两个运算量,其功能是将两个运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行运算量的各个相应位分别进行“与与”运算。运算。 运算规则为运算规则为: 1&1=1 0&1=0 1&0=0 0&0=0 例例11.4 对于无符号数对于无符号数a=(173)10=(10101101)2, b=(203)10=(11001011)2, 则则a&b = (10001001)2 =(137)10 10101101& 11001011 1000100112例例11.5 对于有符号数对于有符号数a=(-83)10=(10101101)2 , b=(-53)10=(11001011)2 , 则则a&b = (10001001)2 =(-119)10 。以上二进制形式是负数的补码。以上二进制形式是负数的补码。C程序如右上所示。程序如右上所示。C程序:程序: # include int main() unsigned char a=173,b=203,c; c=a&b; printf(“a&b=%d”,c); return 0;运行结果为:运行结果为: a&b=137 10101101& 11001011 10001001C程序:程序:# include int main() char a=-83,b=-53,c; c=a&b; printf(“a&b=%d”,c); return 0;运行结果为:运行结果为: a&b=-1191311.2 11.2 位运算位运算11.2.5 按位或运算按位或运算 按位按位“或或”运算符要求有两个运算量,其功能是将运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行两个运算量的各个相应位分别进行“或或”运算。运算。 运算规则为运算规则为: 1|1=1 0|1=1 1|0=1 0&0=0例例11.6 对于无符号数对于无符号数a=(173)10=(10101101)2,b=(203)10=(11001011)2,则,则a|b = (11101111)2 =(239)10 10101101| 11001011 1110111114 例例11.7 对于有符号数对于有符号数 a=(-83)10=(10101101)2, b=(-53)10=(11001011)2, 则则a|b = (11101111)2 =(-17)10C程序: # include int main() unsigned char a=173,b=203,c; c=a|b; printf(“a|b=%d”,c); return 0; 运行结果:运行结果: a|b=239 10101101| 11001011 1110111115C程序: # include int main()char a=-83,b=-53,c; c=a|b; printf(“a|b=%d”,c); return 0; 运行结果为:运行结果为: a|b= -171611.2 11.2 位运算位运算11.2.6 按位异或运算按位异或运算 按按位位“异异或或”运运算算符符要要求求有有两两个个运运算算量量,其其功功能能是是将将两两个个运算量的各个相应位分别进行运算量的各个相应位分别进行“异或异或”运算。运算。 运算规则为运算规则为: 11=0 01=1 10=1 0&0=0 。例例11.8 对于无符号数对于无符号数 a=(173)10=(10101101)2, b=(203)10=(11001011)2, 则则ab = (11101111)2 =(102)10 10101101 11001011 01100110 C程序:程序: # include int main()unsigned char a=173,b=203,c; c=ab; printf(“ab=%d”,c); return 0; 运行结果:运行结果: ab=102 1711.3 位运算应用举例位运算应用举例例例11.9 对内存中的二进制数对内存中的二进制数“01010100”进行下列操进行下列操作:作: 1. 用用“按位与按位与”实现实现: : (1)把存储此二进制数的内存单元清零;)把存储此二进制数的内存单元清零; (2)把此二进制数的)把此二进制数的2到到4位取出(从位取出(从0位开始);位开始); (3)把此二进制数的)把此二进制数的2、3、5位留下。位留下。 2. 用用“按位或按位或”运算把此二进制数后四位置运算把此二进制数后四位置1 (写写出实现方法出实现方法) 。18(3)要把二进制数要把二进制数2、3、5位留下,位留下, 与与00101100进行按位与即可,进行按位与即可, 其运算过程为:其运算过程为: 01010100& 00101100 000001002.2.把此二进制数后四位置把此二进制数后四位置1,与与00001111进行按位或即可,进行按位或即可, 其运算过程为:其运算过程为: 01010100| | 00001111 010111111.1.用按位与实现:用按位与实现:(1) 要把存储此二进制数的内存要把存储此二进制数的内存 单元清零,与单元清零,与0按位与即可,按位与即可, 其运算过程为:其运算过程为: 01010100& 00000000 00000000(2)要取出二进制数要取出二进制数2到到4位位, 与与00011100进行按位与即可,进行按位与即可, 其运算过程为:其运算过程为: 01010100& 00011100 0001010019例例11.10 编程将一个十六进制整型数转换为二进制数。编程将一个十六进制整型数转换为二进制数。 设该整型数占设该整型数占16位。位。 将将十十六六进进制制数数转转换换为为二二进进制制数数的的方方法法很很多多,这这里里我我们们利利用用位位运运算算来来进进行行处处理理,思思路路:对对一一个个十十六六进进制制整整型型数数n的的二二进进制制(16位位)形形式从最高位到最低位的每一位进行测试,依次求出其值即可。式从最高位到最低位的每一位进行测试,依次求出其值即可。 具具体体方方法法:设设置置一一个个屏屏蔽蔽字字mask(二二进进制制为为1000 0000 0000 0000。其其相相应应的的十十六六进进制制形形式式为为0x8000),将将mask与与n进进行行“与与”运运算算得得出出的的值值如如为为0则则最最高高位位为为0,否否则则最最高高位位为为1;再再将将mask右右移移一一位位后后,与与n进进行行“与与”运运算算得得出出次次高高位位,依依此此类类推推,求求出出每每一位的值。一位的值。20# include int main()unsigned int i,n,b,mask; mask=0x8000; printf(Input a hex number to convert:); scanf(%x,&n); printf(nBinary of %0x is:,n); for(i=0;i1; return 0; 运行情况:运行情况:Input a hex number to convert: f fBinary of f f is: 00000000-11111111Input a hex number to convert: 127Binary of 0127 is:00000001-00100111 21例例11.11 循环移位。循环移位。 所谓循环移位是指:在移位时不丢失移位前原数据所谓循环移位是指:在移位时不丢失移位前原数据的所有位,将其作为另一端的补入位。的所有位,将其作为另一端的补入位。 如:将如:将11110001循环右移循环右移1位,应为位,应为11111000。 11110001循环右移循环右移3位,应为位,应为00111110。 22实现将无符号数实现将无符号数a循环右移循环右移n位的方法位的方法: (1) 将将a左移左移16-n位存入位存入b中;中; (2) 将将a右移右移n位存入位存入c中;中; (3) 将将b与与c按位进行按位进行“或运算或运算”,则结果便为所需结果。,则结果便为所需结果。23l# include lint main()lunsigned int n,a,b,c,d;l printf(Input a Hex number:);l scanf(%x,&a);l printf(nInput the number of bit to move:);l scanf(%d,&n);l b=an;l d=b|c;l printf(nThe result of move:%x,d);l return 0;l运行情况:运行情况:Input a Hex number:f2d3Input the number of bit to move:3The result of move:7e5a 2411.4 位段结构位段结构1. 位段结构的概念位段结构的概念 位段结构是一种结构体类型,只不过是在结构体中含有以位为单位定位段结构是一种结构体类型,只不过是在结构体中含有以位为单位定义存储长度的成员。采用这种结构可以节省存储空间、方便某些特定的操义存储长度的成员。采用这种结构可以节省存储空间、方便某些特定的操作。作。 2 . 位段结构的定义位段结构的定义struct bytedata unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ unsigned C: 3 ; /*占占3位位*/ unsigned d : 2 ; /*占占2位位*/ 位段结构中位段的定义:位段结构中位段的定义: unsigned : 例如25其存储结构如下图:其存储结构如下图:struct bytedata unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ unsigned : 3 ; /*占占3位,无字段名,不能引用位,无字段名,不能引用*/ unsigned d : 2 ; /*占占2位位*/ 如如果果需需要要可可以以跳跳过过某某些些不不用用的的位位,只只要要将将这这些些位位段段不不指指定定位位段段名名就就无法引用。例如:无法引用。例如: 26 如如果果某某一一位位段段为为位位数数为为0的的无无名名位位段段,则则表表示示其其下下一一个个位位段段从从另另一一个个字节开始。字节开始。 还可以在一个结构体中混用位段与普通结构体成员。例如:还可以在一个结构体中混用位段与普通结构体成员。例如:struct bytedata int i; /*非位段,整型,占非位段,整型,占2个字节个字节*/ unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ unsigned : 0 ; /*无名,无名,0长度,则下位段从下字节开始长度,则下位段从下字节开始*/ unsigned c : 2 ; /*从第从第4个字节开始占个字节开始占2位位*/27 对位段的引用方法和引用结构体变量中的成员相同对位段的引用方法和引用结构体变量中的成员相同 ,例如,若,例如,若data是是struct bytedata类型的变量,类型的变量,即有:即有: struct bytedata data ;则可以用后面的形式引用每个成员:则可以用后面的形式引用每个成员:data.i、data.a、data.b、data.c。 可以用下面形式输出每个成员:可以用下面形式输出每个成员: printf(“%d, %d, %d, %d”, printf(“%d, %d, %d, %d”, data.a , data.b ,data.c, data.c ); data.a , data.b ,data.c, data.c ); 注意每个位段存储的最大值:注意每个位段存储的最大值: data.a的最大值是的最大值是3 3, data.b的最的最大值是大值是1 1。若用大于最大值的数赋值,只取其相应的低位,如将。若用大于最大值的数赋值,只取其相应的低位,如将6 6(二(二进制进制110110)赋给)赋给data.a,则其存储的是,则其存储的是低低2 2位(二进制位(二进制1010),即),即2 2。3.位段的引用位段的引用 2811.5 本章小结本章小结 l本章介绍了本章介绍了C语言的位运算语言的位运算 。l首先,介绍了首先,介绍了C语言的位运算符。语言的位运算符。l接下来,对接下来,对C语言的各个位运算符的用法进行了语言的各个位运算符的用法进行了详细介绍。详细介绍。l之后,举例说明之后,举例说明C语言位运算的应用方法。语言位运算的应用方法。l最后,介绍了最后,介绍了C语言的位段结构语言的位段结构 29
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号