《kj-第11章位运算课件.ppt》由会员分享,可在线阅读,更多相关《kj-第11章位运算课件.ppt(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第1页第第11章章 位运算位运算 本章概述 本章的学习目标主要内容第2页本章概述本章概述lC语言有一个重要特点就是可以直接对二进制位语言有一个重要特点就是可以直接对二进制位进行操作,即位运算。进行操作,即位运算。l二进制位简称位(二进制位简称位(bit),其值为),其值为0或或1。计算机真。计算机真正执行的正是由正执行的正是由0和和1构成的机器指令,计算机内构成的机器指令,计算机内数据也是由二进制表示的。数据也是由二进制表示的。 l数在计算机内均是以补码的形式存储的数在计算机内均是以补码的形式存储的 。l本章介绍位运算和位段结构的有关知识。本章介绍位运算和位段结构的有关知识。第3页本章的学习目
2、标本章的学习目标l本章教学目的:理解位运算的概念,本章教学目的:理解位运算的概念,掌握基本位运算运算符的使用,理解掌握基本位运算运算符的使用,理解位段的概念。位段的概念。l本章教学重点:基本位运算运算符的本章教学重点:基本位运算运算符的使用使用l本章教学难点:位段的概念本章教学难点:位段的概念第4页主要内容主要内容11.1 位运算符位运算符 11.2 位运算位运算 11.3 位运算应用举例位运算应用举例 11.4 位段结构位段结构 第5页11.1 位运算符位运算符位运算符位运算符功能功能举例举例按位取反按位取反a:对变量:对变量a的全部位取反的全部位取反左移左移 a右移右移 a2:将变量:将变
3、量a的各位全部右移的各位全部右移2位,对于位,对于无符号数和正整数,高位补无符号数和正整数,高位补0;对于负整数,;对于负整数,高位补高位补1(适用于(适用于turboc系统)系统)&按位与按位与 a&b:对:对a与与b的各对应位进行的各对应位进行“按位与按位与”运算运算|按位或按位或 a|b:对:对a与与b的各对应位进行的各对应位进行“按位或按位或”运算运算按位异或按位异或 ab:对:对a与与b的各对应位进行的各对应位进行“按位异或按位异或”运运算算第6页11.2 11.2 位运算位运算 取反运算取反运算“”是一个单目运算符,运算量在运算是一个单目运算符,运算量在运算符之后,取反运算的功能是
4、将一个数据中所有位都取符之后,取反运算的功能是将一个数据中所有位都取其相反值,即其相反值,即1变变0,0变变1。 运算规则为:运算规则为: 1=0 0=1例例11.1 对于无符号的字符型数据对于无符号的字符型数据a=(18)10 =(00010010)2 ,则则a等于等于(11101101)2 ,即,即(237)10C程序如下:程序如下:11.2.1 按位取反运算按位取反运算第7页# include int main() unsigned char a=18,b; b=a; printf(“a=%d”,b); return 0; 运行结果为:运行结果为: a= 237 注意以下程序与左面程序及
5、注意以下程序与左面程序及运行结果的区别:运行结果的区别: # include int main() char a=18,b; b=a; printf(“a=%d”,b); return 0;运行结果:运行结果:-19 前一个程序结果很好理解,后一个因为前一个程序结果很好理解,后一个因为a是带符号数据,因是带符号数据,因此此a=(11101101)2的结果是一负数的补码,转换为原码时,第的结果是一负数的补码,转换为原码时,第1位位符号位不变,对剩余的部分先减符号位不变,对剩余的部分先减1,再全部取反,因此得到的二,再全部取反,因此得到的二进制原码为:进制原码为:10010011,即十进制的,即十
6、进制的-19。 第8页11.2 11.2 位运算位运算11.2.2 左移运算左移运算 左移运算左移运算“”是一个双目运算符,左移运算的是一个双目运算符,左移运算的功能是将一个数据所有位向左移若干位,左边(高位)功能是将一个数据所有位向左移若干位,左边(高位)移出的部分舍去,右边(低位)自动补零。移出的部分舍去,右边(低位)自动补零。 例例11.2 对于无符号字符型数据对于无符号字符型数据 a=(18)10 =(00010010)2 , a 3的结果是的结果是(10010000)2 ,即(,即(144)10第9页C程序如下:程序如下: # include int main() unsigned
7、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”是一个双目运算符,右移运算的功能是一个双目运算符,右移运算的功能是将一个数据所有位向右移若干位,右边(低位)移出的是将一个数据所有位向右移若干位,右边(低位)移出的部分舍去,左边(高位)
8、移入的二进制数分两种情况:对部分舍去,左边(高位)移入的二进制数分两种情况:对于无符号数和正整数,高位补于无符号数和正整数,高位补0;对于负整数,高位补;对于负整数,高位补1(适用于适用于turboc系统系统)。)。 例例11.3 对于无符号字符型数据对于无符号字符型数据 a=(18)10 =(00010010)2 , 则则 a 3的结果是的结果是(00000010)2,即(,即(2)10第11页C程序:程序: # include int main() unsigned char a=18, b; b=a3; printf(“a3=%d”,b); return 0;运行结果为:运行结果为: a
9、3=2第12页11.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 10001001第13页例例11.5 对于有符号数对于
10、有符号数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() ch
11、ar a=-83,b=-53,c; c=a&b; printf(“a&b=%d”,c); return 0;运行结果为:运行结果为: a&b=-119第14页11.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
12、 = (11101111)2 =(239)10 10101101| 11001011 11101111第15页 例例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 11101111第16页C程序: # i
13、nclude int main()char a=-83,b=-53,c; c=a|b; printf(“a|b=%d”,c); return 0; 运行结果为:运行结果为: a|b= -17第17页11.2 11.2 位运算位运算11.2.6 按位异或运算按位异或运算 按位按位“异或异或”运算符要求有两个运算量,其功能是将两个运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行运算量的各个相应位分别进行“异或异或”运算。运算。 运算规则为运算规则为: 11=0 01=1 10=1 0&0=0 。例例11.8 对于无符号数对于无符号数 a=(173)10=(10101101)2, b
14、=(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 第18页11.3 位运算应用举例位运算应用举例例例11.9 对内存中的二进制数对内存中的二进制数“01010100”进行下列操进行下列操作:作: 1. 用用“按位与按位与”实现实现: : (1)把存储此二进制数的内存单元清零;
15、)把存储此二进制数的内存单元清零; (2)把此二进制数的)把此二进制数的2到到4位取出(从位取出(从0位开始);位开始); (3)把此二进制数的)把此二进制数的2、3、5位留下。位留下。 2. 用用“按位或按位或”运算把此二进制数后四位置运算把此二进制数后四位置1 (写写出实现方法出实现方法) 。第19页(3)要把二进制数要把二进制数2、3、5位留下,位留下, 与与00101100进行按位与即可,进行按位与即可, 其运算过程为:其运算过程为: 01010100& 00101100 000001002.2.把此二进制数后四位置把此二进制数后四位置1,与与00001111进行按位或即可,进行按位或
16、即可, 其运算过程为:其运算过程为: 01010100| | 00001111 010111111.1.用按位与实现:用按位与实现:(1) 要把存储此二进制数的内存要把存储此二进制数的内存 单元清零,与单元清零,与0按位与即可,按位与即可, 其运算过程为:其运算过程为: 01010100& 00000000 00000000(2)要取出二进制数要取出二进制数2到到4位位, 与与00011100进行按位与即可,进行按位与即可, 其运算过程为:其运算过程为: 01010100& 00011100 00010100第20页例例11.10 编程将一个十六进制整型数转换为二进制数。编程将一个十六进制整型
17、数转换为二进制数。 设该整型数占设该整型数占16位。位。 将十六进制数转换为二进制数的方法很多,这里我们利用位运算将十六进制数转换为二进制数的方法很多,这里我们利用位运算来进行处理,思路:对一个十六进制整型数来进行处理,思路:对一个十六进制整型数n的二进制(的二进制(16位)形位)形式从最高位到最低位的每一位进行测试,依次求出其值即可。式从最高位到最低位的每一位进行测试,依次求出其值即可。 具体方法:设置一个屏蔽字具体方法:设置一个屏蔽字mask(二进制为(二进制为1000 0000 0000 0000。其相应的十六进制形式为。其相应的十六进制形式为0 x8000),将),将mask与与n进行
18、进行“与与”运算得出的值如为运算得出的值如为0则最高位为则最高位为0,否则最高位为,否则最高位为1;再将;再将mask右右移一位后,与移一位后,与n进行进行“与与”运算得出次高位,依此类推,求出每一运算得出次高位,依此类推,求出每一位的值。位的值。第21页# include int main()unsigned int i,n,b,mask; mask=0 x8000; printf(Input a hex number to convert:); scanf(%x,&n); printf(nBinary of %0 x is:,n); for(i=0;i1; return 0; 运行情况:运
19、行情况: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 第22页例例11.11 循环移位。循环移位。 所谓循环移位是指:在移位时不丢失移位前原数所谓循环移位是指:在移位时不丢失移位前原数据的所有位,将其作为另一端的补入位。据的所有位,将其作为另一端的补入位。 如:将如:将11110001循环右移循环右移1位,应为位,应为11111000。 11110001循环右移循环
20、右移3位,应为位,应为00111110。 第23页实现将无符号数实现将无符号数a循环右移循环右移n位的方法位的方法: (1) 将将a左移左移16-n位存入位存入b中;中; (2) 将将a右移右移n位存入位存入c中;中; (3) 将将b与与c按位进行按位进行“或运算或运算”,则结果便为所需结果。,则结果便为所需结果。第24页l# 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 s
21、canf(%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 第25页11.4 位段结构位段结构1. 位段结构的概念位段结构的概念 位段结构是一种结构体类型,只不过是在结构体中含有以位为单位定位段结构是一种结构体类型,只不过是在结构体中含有以位为单位定义存储长度的成员。采用这种结构可以节省存储空间、方便某些特定的操义存储长度的成员。
22、采用这种结构可以节省存储空间、方便某些特定的操作。作。 2 . 位段结构的定义位段结构的定义struct bytedata unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ unsigned C: 3 ; /*占占3位位*/ unsigned d : 2 ; /*占占2位位*/ 位段结构中位段的定义:位段结构中位段的定义: unsigned : 例如第26页其存储结构如下图:其存储结构如下图:struct bytedata unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ uns
23、igned : 3 ; /*占占3位,无字段名,不能引用位,无字段名,不能引用*/ unsigned d : 2 ; /*占占2位位*/ 如果需要可以跳过某些不用的位,只要将这些位段不指定位段名如果需要可以跳过某些不用的位,只要将这些位段不指定位段名就无法引用。例如:就无法引用。例如: 第27页 如果某一位段为位数为如果某一位段为位数为0的无名位段,则表示其下一个位段从另一个的无名位段,则表示其下一个位段从另一个字节开始。字节开始。 还可以在一个结构体中混用位段与普通结构体成员。例如:还可以在一个结构体中混用位段与普通结构体成员。例如:struct bytedata int i; /*非位段,
24、整型,占非位段,整型,占2个字节个字节*/ unsigned a : 2 ; /*占占2位位*/ unsigned b : 1 ; /*占占1位位*/ unsigned : 0 ; /*无名,无名,0长度,则下位段从下字节开始长度,则下位段从下字节开始*/ unsigned c : 2 ; /*从第从第4个字节开始占个字节开始占2位位*/第28页 对位段的引用方法和引用结构体变量中的成员相同对位段的引用方法和引用结构体变量中的成员相同 ,例如,若,例如,若data是是struct bytedata类型的变量,类型的变量,即有:即有: struct bytedata data ;则可以用后面的形
25、式引用每个成员:则可以用后面的形式引用每个成员:data.i、data.a、data.b、data.c。 可以用下面形式输出每个成员:可以用下面形式输出每个成员: 注意每个位段存储的最大值:注意每个位段存储的最大值: data.a的最大值是的最大值是3 3, data.b的最的最大值是大值是1 1。若用大于最大值的数赋值,只取其相应的低位,如将。若用大于最大值的数赋值,只取其相应的低位,如将6 6(二(二进制进制110110)赋给)赋给data.a,则其存储的是,则其存储的是低低2 2位(二进制位(二进制1010),即),即2 2。3.位段的引用位段的引用 第29页11.5 本章小结本章小结 l本章介绍了本章介绍了C语言的位运算语言的位运算 。l首先,介绍了首先,介绍了C语言的位运算符。语言的位运算符。l接下来,对接下来,对C语言的各个位运算符的用法进行了语言的各个位运算符的用法进行了详细介绍。详细介绍。l之后,举例说明之后,举例说明C语言位运算的应用方法。语言位运算的应用方法。l最后,介绍了最后,介绍了C语言的位段结构语言的位段结构