下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 12_第12章 位运算

12_第12章 位运算.ppt

12_第12章 位运算

tianxingmeizhou
2010-12-15 0人阅读 举报 0 0 暂无简介

简介:本文档为《12_第12章 位运算ppt》,可适用于工程科技领域

第章位运算第章位运算 位运算符和位运算 位运算举例 位段C语言是为描述系统而设计的因此它应当具有汇编语言所能完成的一些功能。C语言既具有高级语言的特点又具有低级语言的功能因而具有广泛的用途和很强的生命力。第章介绍的指针运算和本章将介绍的位运算就很适合于编写系统软件的需要是C语言的重要特色。在计算机用于检测和控制领域中要用到位运算的知识因此读者应当学习和掌握本章的内容。所谓位运算是指进行二进制位的运算。在系统软件中常要处理二进位的问题。例如将一个存储单元中的各二进位左移或右移一位两个数按位相加等。C语言提供位运算的功能与其他高级语言(如PASCAL)相比它显然具有很大的优越性。 “按位与”运算符()参加运算的两个数据按二进位进行“与”运算。如果两个相应的二进位都为则该位的结果值为否则为。即    ====例如: 并不等于应该是按位与。=()= 位运算符和位运算因此的值得。如果参加是负数运算的是负数(如)则以补码形式表示为二进制数然后按位进行“与”运算。按位与有一些特殊的用途:()清零。 如果想将一个单元清零即使其全部二进位为只要找一个二进制数其中各个位符合以下条件:原来的数中为的位新数中相应位为。然后使二者进行运算即可达到清零目的。如:原有数为另找一个数设它为它符合以上条件即在原数为的位置上它的位值均为。将两个数进行运算:()其道理是显然的。当然也可以不用这个数而用其他数(如)也可以只要符合上述条件即可。()取一个数中某些指定位。如有一个整数a(个字节)想要其中的低字节。只需将a与()按位与即可。见图。图c=abb为八进制数的运算后c只保留a的低字节高字节为。如果想取两个字节中的高字节只需c=a (表示八进制数的)。()要想将哪一位保留下来就与一个数进行运算此数在该位取如:有一数想把其中左面第、、、、位保留下来可以这样运算:(十进制数)()(十进制数)(十进制数)即 a=b=c=ab=。 按位或运算符(|)两个相应的二进位中只要有一个为该位的结果值为。即|= |= |= |=。例如:|将八进制数与八进制数进行按位或运算。(|)低位全为。如果想使一个数a的低位改为只需将a与进行按位或运算即可。按位或运算常用来对一个数据的某些位定值为(置位)。如:a是一个整数(位)有表达式a|则低位全置为。高位保留原样。  “异或”运算符(∧)异或运算符∧也称XOR运算符。它的规则是若参加运算的两个二进位相同为(假)不同为(真)。即∧= ∧= ∧= ∧=如:(十进制数八进制数)(∧)(十进制数八进制数)(十进制数八进制数)即∧结果为(八进制数)。“异或”的意思是判断两个相应的位值是否为“异”为“异”(值不同)就取真()否则为假()。  下面举例说明∧运算符的应用:  ()使特定位翻转  假设有想使其低位翻转即变为变为。可以将它与进行∧运算即(∧)结果值的低位正好是原数低位的翻转。要使哪几位翻转就将与其进行∧运算的该几位置为即可。这是因为原数中值为的位与进行∧运算得原数中的位值与进行∧运算的结果得。()与相∧保留原值。如:∧=(∧)因为原数中的与进行∧运算得∧得故保留原数。()交换两个值不用临时变量假如a=b=。想将a和b的值互换可以用以下赋值语句实现:a=a∧bb=b∧aa=a∧b可以用下面的竖式来说明:a=(∧)b=a=(a∧b的结果a已变成)(∧)b=b=(b∧a的结果b已变成)(∧)a=a=(a∧b的结果a变成)即等效于以下两步:①b=b∧(a∧b)=b∧a∧b=a∧b∧b=a∧=a它相当于上面的前两个赋值语句:“a=a∧b”和“b=b∧a”。b∧b的结果为因为同一个数与本身相∧结果必为。现在b已得到a的值。在上式中除了第一个b以外其余的a、b都是指原来的a、b。②再执行a=a∧b=(a∧b)∧(b∧a∧b)=a∧b∧b∧a∧b=a∧a∧b∧b∧b=b。a得到b原来的值。 “取反”运算符(~)~是一个单目(元)运算符用来对一个二进制数按位取反即将变变。例如~是对八进制数(即二进制数)按位求反。(~)  ↓即八进制数。因此~的值为八进制数。不要以为~的值是。下面举一例说明~运算符的应用。若一个整数a为位想使最低一位为可以用a=a即二进制数如果a的值为八进制数a的运算可以表示如下:()a的最后一个二进位变成。但如果将C源程序移植到以位存放一个整数的计算机系统(如VAX)上由于一个整数用个字节(位表示)想将最后一位变成就不能用a了。读者可以自己算一下当a=时a的结果是什么?为了适应以位存放一个整数的计算机系统应改用a这样改动使移植性差了可以改用a=a~它对以位和以位存放一个整数的情况都适用不必作修改。因为在以个字节存储一个整数时的二进制形式为~是(注意~不等于弄清~运算符和负号运算符的不同)。在以个字节存储一个整数时~是。~运算符的优先级别比算术运算符、关系运算符、逻辑运算符和其他位运算符都高例如:~ab先进行~a运算然后进行运算。 左移运算符(<<)用来将一个数的各二进位全部左移若干位。例如:a=a<<将a的二进制数左移位右补。若a=即二进制数左移位得即十进制数(为简单起见我们用位二进制数表示十进制数如果用位结果是一样的)。高位左移后溢出舍弃不起作用。左移位相当于该数乘以左移位相当于该数乘以*=。上面举的例子<<=即乘了。 但此结论只适用于该数左移时被溢出舍弃的高位中不包含的情况。例如假设以一个字节(位)存一个整数若a为无符号整型变量则a=时左移一位时溢出的是而左移位时溢出的高位中包含。左移比乘法运算快得多,有些C编译程序自动将乘的运算用左移一位来实现,将乘n的幂运算处理为左移n位。 右移运算符(>>)a>>表示将a的各二进位右移位。移到右端的低位被舍弃,对无符号数,高位补。如a=时:a为a>>为此二位舍弃右移一位相当于除以,右移n位相当于除以n。在右移时,需要注意符号位问题。对无符号数,右移时左边高位移入。对于有符号的值,如果原来符号位为(该数为正),则左边也是移入,如同上例表示的那样。如果符号位原来为(即负数),则左边移入还是,要取决于所用的计算机系统。有的系统移入,有的移入。移入的称为“逻辑右移”,即简单右移。移入的称为“算术右移”。例如,a的值为八进制数。a:a>>:(逻辑右移时)a>>:(算术右移时)在有些系统上,a>>得八进制数,而在另一些系统上可能得到的是。TurboC和其他一些C编译采用的是算术位移,即对有符号数右移时,如果符号位原来为左面移入高位的是。 位运算赋值运算符位运算符与赋值运算符可以组成复合赋值运算符如:=,|=,>>=,<<=,∧=例如,a=b相当于a=ab。a<<=相当于:a=a<<。 不同长度的数据进行位运算如果两个数据长度不同(例如long型和int型)进行位运算时(如ab,而a为long型,b为int型),系统会将二者按右端对齐。如果b为正数,则左侧位补满。若b为负数,左端应补满。如果b为无符号整数型,则左侧添满。 位运算举例例取一个整数a从右端开始的~位。可以这样考虑:①先使a右移位。见图。图(a)是未右移时的情况,(b)图是右移位后的情况。目的是使要取出的那几位移到最右端。   图右移到右端可以用下面方法实现:a>>②设置一个低位全为,其余全为的数。可用下面方法实现:~(~<<)~的全部二进制为全左移位这样右端低位为。见下面所示::…~:…~<<:…~(~<<):…③将上面二者进行运算。即(a>>)~(~<<)根据上一节介绍的方法与低位为的数进行运算就能将这位保留下来。程序如下:main( ){unsignedabcdscanf("o"a)b=a>>c=~(~<<)d=bcprintf("odnodn"aadd)}  运行情况如下:(a的值)(d的值)输入a的值为八进制数即十进制数其二进制形式为。经运算最后得到的d为即八进制数十进制数。可以任意指定从右边第m位开始取其右边n位。只需将程序中的“b=a>>”改成“b=a>>(mn)”以及将“c=~(~<<)”改成“c=~(~<<n)”即可。例循环移位。要求将a进行右循环移位。见下图图表示将a右循环移n位。即将a中原来左面(n)位右移n位原来右端n位移到最左面n位。今假设用两个字节存放一个整数。为实现以上目的可以用以下步骤:①将a的右端n位先放到b中的高n位中。可以用下面语句实现:b=a<<(n)②将a右移n位其左面高位n位补。可以用下面语句实现:c=a>>n③将c与b进行按位或运算。即:c=c|b程序如下:main( ){unsignedabcintnscanf("a=on=d"an)b=a<<(n)c=a>>nc=c|bprintf("ono"ac)}运行情况如下:a=n=运行开始时输入八进制数即二进制数循环右移位后得二进制数即八进制数。同样可以左循环位移。 位段以前曾介绍过对内存中信息的存取一般以字节为单位。实际上有时存储一个信息不必用一个或多个字节例如“真”或“假”用或表示只需位即可。在计算机用于过程控制、参数检测或数据通信领域时控制信息往往只占一个字节中的一个或几个二进位常常在一个字节中放几个信息。那么怎样向一个字节中的一个或几个二进位赋值和改变它的值呢?可以用以下两种方法:()可以人为地在一个字节data中设几项。例如:a、b、c、d分别占位、位、位、位(见图)。如果想将c的值变为(设c原来为)可以这样:  图①将数左移位使成为右面起第~位。②将data与“<<”进行“按位或”运算即可使c的值变成。如果c的原值不为应先使之为。可以用下面方法:data=data的二进制表示为abcd也就是使第~位全为,其他位全为。它与data进行运算,使第~位为,其余各位保留data的原状。这个称为“屏蔽字”,即把c以外的信息屏蔽起来,不受影响,只使c改变为。但要找出和记住这个数比较麻烦。可以用data=data~(<<)是c的最大值,c共占位,最大值为即。<<是将移到~位。再取反,就使~位变成,其余位全是。即:<<:~(<<):这样可以实现对c清,而不必计算屏蔽码。将上面几步结合起来,可以得到data=data~(<<)|(n)<<赋予~位为n为应赋给c的值(例如)。n的作用是只取n的右端位的值,其余各位置,即把n放到最后位上,(n)<<,就是将n置在~位上。见下面:  data~(<<):||(n)<<:||(按位或运算)||可见,data的其他位保留原状未改变,而第~位改变为(即)了。但是用以上办法给一个字节中某几位赋值太麻烦了。可以用下面介绍的位段结构体的方法。()位段C语言允许在一个结构体中以位为单位来指定其成员所占内存长度这种以位为单位的成员称为“位段”或称“位域”(bitfield)。利用位段能够用较少的位数存储数据。例如:  struct packeddata    {unsigned a∶unsigned b∶unsigned c∶unsigned d∶int i    }data见图。其中a、b、c、d分别占位、位、位、位。i为整型。共占个字节。  图也可以使各个位段不恰好占满一个字节。如: struct packeddata  {unsigned a∶unsigned b∶unsigned c∶int i  }  struct packeddata data图见图。其中a、b、c共占位占个字节多不到个字节。它的后面为int型占个字节。在a、b、c之后位空间闲置不用i从另一字节开头起存放。注意在存储单元中位段的空间分配方向因机器而异。在微机使用的C系统中一般是由右到左进行分配的如图。但用户可以不必过问这种细节。对位段中的数据引用的方法。如:图data.a=  data.b=  data.c=注意位段允许的最大值范围。如果写data.a=就错了。因为dataa只占位最大值为。在此情况下自动取赋予它的数的低位。例如的二进制数形式为而data.a只有位取的低位故data.a得值。关于位段的定义和引用有几点要说明:()位段成员的类型必须指定为unsigned或int类型。()若某一位段要从另一个字开始存放。可以用以下形式定义:unsigned a∶unsigned b∶一个存储单元unsigned∶unsigned c∶ (另一存储单元)本来a、b、c应连续存放在一个存储单元(字)中由于用了长度为的位段其作用是使下一个位段从下一个存储单元开始存放。因此现在只将a、b存储在一个存储单元中c另存放在下一个单元。(上述“存储单元”可能是一个字节可能是个字节视不同的编译系统而异。)()一个位段必须存储在同一存储单元中不能跨两个单元。如果第一个单元空间不能容纳下一个位段则该空间不用而从下一个单元起存放该位段。()可以定义无名字段。如:unsigned a∶unsigned∶(这两位空间不用)unsignedb∶unsignedc∶见图。在a后面的是无名位段该空间不用。图()位段的长度不能大于存储单元的长度也不能定义位段数组。()位段可以用整型格式符输出。如:printf("ddd"data.adata.bdata.c)当然也可以用u、o、x等格式符输出。()位段可以在数值表达式中引用它会被系统自动转换成整型数。例如:dataadatab是合法的。

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/44

12_第12章 位运算

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利