第11章位运算精选文档.ppt
第第11章章 位运算位运算本讲稿第一页,共三十二页11.1 数值在计算机中的表示数值在计算机中的表示 计算机中采用二进制存储各种信息,这是由计算机电路所使用的元器件性质决定的。计算机中的二值电路只能表示两个数值:0和1(数码“0”表示低电位,数码“1”表示高电位)。二进制的使用使得计算机设备数值运算简单、电路实现方便、成本低廉等优点得到了充分体现。本讲稿第二页,共三十二页11.1.1 二进制数的简单运算1算术运算加法:0+0=0,0+1=1+0=1,1+1=0(有进位)减法:0-0=1-1=0,1-0=1,0-1=1(向高位借位)乘法:00=10=01=0,11=1除法:0/1=0,1/1=1本讲稿第三页,共三十二页2逻辑运算或(|):0|0=0,0|1=1|0=1|1=1与(&):0&0=0&1=1&0=0,1&1=1非(!):!0=1,!1=0异或():00=11=0,01=10=1本讲稿第四页,共三十二页 11.1.2 数值在计算机中的表示 1原码 原码的最高位为符号位:用0表示正数,用1表示负数;数值部分用二进制的绝对值表示。例如:+105=01101001 -105=11101001 +0=00000000 -0=10000000 一个字节长度的二进制数原码表示的数值范围为:-127+127。本讲稿第五页,共三十二页 2反码 正数的反码与其原码相同,负数的反码等于其绝对值各位求反。例如:+105反=01101001 -105反=10010110 +0反=00000000 -0反=11111111 一个字节长度的二进制数反码表示的数值范围为:-127+127。本讲稿第六页,共三十二页 3补码 正数的补码与其原码相同,负数的补码是把其原码除符号位外的各位先求其反码,然后在最低位加1。常用的一个公式是:X-YX(Y的补码)X(Y的反码1)本讲稿第七页,共三十二页 上式描述的意义在于:利用补码表示数值,使得计算机在进行数值运算时,可将加减算法统一转换为加法运算。例如:+105补=01101001 -105补=10010111 0补=00000000 -1补=11111111 一个字节长度的二进制数补码表示的数值范围为:-128+127。本讲稿第八页,共三十二页11.2 位位 运运 算算 11.2.1 位运算符C语言提供了6种位运算符,见表11-1。本讲稿第九页,共三十二页表11-1 位 运 算 符 位运算符功 能&按位与|按位或按位异或取反右移本讲稿第十页,共三十二页 11.2.2 位运算符功能实现 1“按位与”运算 按位与运算符“&”是双目运算符,其功能是参与运算的两数各对应的二进制位相“与”。只有对应的两个二进制位均为1时,结果位才为1,否则为0。参与运算的数以补码方式出现。例如,9&5可写算式如下:本讲稿第十一页,共三十二页 00001001 (9的二进制补码)&00000101 (5的二进制补码)00000001 (1的二进制补码)可见,9&5=1。按位与运算通常用来对某些位清0或保留某些位。例如,把a 的高8位清0,保留低8位,可作a&255 运算(255 的二进制数为0000000011111111)。本讲稿第十二页,共三十二页【例11.1】/*程序功能:“按位与”运算示例*/main()int a=9,b=5,c;c=a&b;printf(a=%dnb=%dnc=%dn,a,b,c);程序运行结果:a=9b=5c=1本讲稿第十三页,共三十二页 2“按位或”运算 “按位或”运算符“|”是双目运算符,其功能是参与运算的两数各对应的二进制位相“或”。只要对应的两个二进制位有一个为1时,结果位就为1。参与运算的两个数均以补码方式出现。例如,9|5可写算式如下:00001001|00000101 00001101 (十进制为13)可见,9|5=13。本讲稿第十四页,共三十二页【例11.2】/*程序功能:“按位或”运算示例*/main()int a=9,b=5,c;c=a|b;printf(a=%dnb=%dnc=%dn,a,b,c);程序运行结果:a=9b=5c=13本讲稿第十五页,共三十二页 3“按位异或”运算 按位异或运算符“”是双目运算符,其功能是参与运算的两数各对应的二进制位相异或。当两个对应的二进制位相异时,结果为1。参与运算数仍以补码方式出现。例如,95可写成算式如下:00001001 00000101 00001100 (十进制为12)本讲稿第十六页,共三十二页【例11.3】/*程序功能:“按位异或”运算示例*/main()int a=9;a=a5;printf(a=%dn,a);程序运行结果:a=12本讲稿第十七页,共三十二页 4“按位求反”运算 求反运算符“”为单目运算符,具有右结合性,其功能是对参与运算的数的各二进制位按位求反。例如,9的运算:(0000000000001001)结果为 1111111111110110本讲稿第十八页,共三十二页 5“左移”运算 左移运算符“”是双目运算符,其功能是把“”左边的运算数的各二进制位全部左移若干位,由“”右边的数指定移动的位数。其中,移位过程中,高位丢弃,低位补0。例如,a”是双目运算符,其功能是把“”左边的运算数的各二进制位全部右移若干位,“”右边的数指定移动的位数。例如,取a=15,则a2表示把000001111右移为00000011(十进制3)。应该注意的问题是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。本讲稿第二十页,共三十二页【例11.4】/*程序功能:“右移”运算示例*/main()unsigned a,b;printf(input a number:);scanf(%d,&a);b=a5;printf(a=%dnb=%dn,a,b);本讲稿第二十一页,共三十二页程序运行情况:input a number:100a=100b=3本讲稿第二十二页,共三十二页*11.3 位位 段段 简简 介介 在实际应用中,有些信息在存储过程中,并不需要占用一个或多个完整的字节,而只需占几个或一个二进制位。例如在存放一个逻辑值时,只有0和1两种状态,用一位二进制位即可。为了节省存储空间,满足各种需求,并使程序处理简便,语言提供了一种数据结构,称为“位段”。本讲稿第二十三页,共三十二页 所谓“位段”,就是把一个字节中的二进制位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样,就可以把几个不同的对象用一个字节的二进制位段来表示。本讲稿第二十四页,共三十二页 11.3.1 位段的定义和位段变量的说明 位段的定义与结构体的定义相仿,其形式为struct 位段结构名 位段列表;其中,位段列表的形式为类型说明符 位段名:位段长度 例如:struct bs int a:8;int b:2;int c:6;本讲稿第二十五页,共三十二页 位段变量的说明与结构体变量的说明方式相同。可采用先定义后说明、同时定义说明或直接说明这三种方式。例如:struct bs int a:8;int b:2;int c:6;data;说明data为bs变量,共占两个字节。其中,位段a占8位,位段b占2位,位段c占6位。本讲稿第二十六页,共三十二页 在对位段定义时须注意以下问题:(1)一个位段必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位段时,应从下一单元起存放该位段。(2)由于位段不允许跨越两个字节,因此位段的长度不能大于一个字节的长度,也就是说,不能超过8位二进制位。(3)位段定义中也可无位段名,其目的只用来作填充或调整位置,且不能使用。本讲稿第二十七页,共三十二页 例如:struct k int a:1 int :2 /*该2位不能使用*/int b:3 int c:2 ;可见,位段本质上就是一种结构类型,不过其成员是按二进制位分配的而已。本讲稿第二十八页,共三十二页11.3.2 位段的使用位段的使用和结构成员的使用相同,其一般形式为位段变量名.位段名其中,位段允许用各种格式输出。【例11.5】/*程序功能:位段的定义及简单应用示例*/main()struct bs 本讲稿第二十九页,共三十二页 unsigned a:1;unsigned b:3;unsigned c:4;bit,*pbit;bit.a=1;bit.b=7;bit.c=15;printf(%d,%d,%dn,bit.a,bit.b,bit.c);pbit=&bit;pbit-a=0;pbit-b&=3;本讲稿第三十页,共三十二页 pbit-c|=1;printf(%d,%d,%dn,pbit-a,pbit-b,pbit-c);程序运行情况:1,7,150,3,15本讲稿第三十一页,共三十二页 说明:(1)本例中定义了位段结构bs,三个位段为a,b,c,说明了bs类型的变量bit和指向bs类型的指针变量pbit。可见,可以使用指针表示位段。(2)在给位段赋值时不允许超过该位段取值范围。(3)注意对位段进行操作的方式(直接取用、指针间接取用)。(4)复合位运算符“&=”处相当于:pbit-b=pbit-b&3。其他操作类似。本讲稿第三十二页,共三十二页