什么是按位或.doc_第1页
什么是按位或.doc_第2页
什么是按位或.doc_第3页
什么是按位或.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

什么是按位或,什么是按位异或,什么是按位与& 按位与, | 按位或 , 按位异或 AND (位与&)OR ( 位或| )XOR ( 位异或 )1 & 1 = 11 & 0 = 00 & 1 = 00 & 0 = 01 | 1 = 11 | 0 = 10 | 1 = 10 | 0 = 01 1 = 01 0 = 10 1 = 10 0 = 01. 按位与运算 按位与运算符&是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。 例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。 按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为0000000011111111)。 main() int a=9,b=5,c; c=a&b; printf(a=%dnb=%dnc=%dn,a,b,c); 2. 按位或运算 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。 例如:9|5可写算式如下: 00001001|00000101 00001101 (十进制为13)可见9|5=13 main() int a=9,b=5,c; c=a|b; printf(a=%dnb=%dnc=%dn,a,b,c); 3. 按位异或运算 按位异或运算符“”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现,例如95可写成算式如下: 0000100100000101 00001100 (十进制为12) main() int a=9; 1.位运算 整数在计算机中用二进制的位来表示,C语言提供一些运算符可以直接操作整数中的位,称为位运算,这些运算符的操作数都必须是整型的。1.1.按位与、或、异或、取反运算 在第3节 “布尔代数”讲过逻辑与、或、非运算,并列出了真值表,对于整数中的位也可以做与、或、非运算,C语言提供了按位与(Bitwise AND)运算符&、按位或(Bitwise OR)运算符|和按位取反(Bitwise NOT)运算符,此外还有按位异或(Bitwise XOR)运算符,下面用二进制的形式举几个例子。图16.1.位运算注意,&、|、运算符都是要做Usual Arithmetic Conversion的(其中有一步是Integer Promotion),运算符也要做Integer Promotion,所以在C语言中其实并不存在8位整数的位运算,操作数在做位运算之前都至少被提升为int型了,上面用8位整数举例只是为了书写方便。比如:unsigned char c = 0xfc;unsigned int i = c;计算过程是这样的:常量0xfc是int型的,赋给c要转成unsigned char,值不变;c的十六进制表示是fc,计算c时先提升为整型(000000fc)然后取反,最后结果是ffffff03。注意,如果把c看成是8位整数的取反,最后结果就得3了,这就错了。为了避免出错,一是尽量避免不同类型之间的赋值,二是每一步计算都要按上一章讲的类型转换规则仔细检查。1.2.移位运算 移位运算符(Bitwise Shift)包括左移。左移将一个整数的各二进制位全部左移若干位,例如0xcfffffff32得到0x33fffffc:图16.3.右移运算最低两位的11被移出去了,最高两位又补了两个0,其它位依次右移两位。和左移类似,移动的位数也必须小于左操作数的总位数,否则结果是Undefined。在一定的取值范围内,将一个整数右移1位相当于除以2,小数部分截掉。当操作数是有符号数时,右移运算的规则比较复杂: 如果是正数,那么高位移入0 如果是负数,那么高位移入1还是0不一定,这是Implementation-defined的。对于x86平台的gcc编译器,最高位移入1,也就是仍保持负数的符号位,这种处理方式对负数仍然保持了“右移1位相当于除以2”的性质。综上所述,由于类型转换和移位等问题,用有符号数做位运算是很不方便的,所以,建议只对无符号数做位运算,以减少出错的可能。习题 1、下面两行printf打印的结果有何不同?请读者比较分析一下。%x转换说明的含义详见第2.9节 “格式化I/O函数”。int i = 0xcffffff3;printf(%xn, 0xcffffff32);printf(%xn, i2);1.3.掩码 如果要对一个整数中的某些位进行操作,怎样表示这些位在整数中的位置呢?可以用掩码(Mask)来表示。比如掩码0x0000ff00表示对一个32位整数的815位进行操作,举例如下。1、取出815位。unsigned int a, b, mask = 0x0000ff00;a = 0x12345678;b = (a & mask) 8; /* 0x00000056 */这样也可以达到同样的效果:b = (a 8) & (0U 8);2、将815位清0。unsigned int a, b, mask = 0x0000ff00;a = 0x12345678;b = a & mask; /* 0x12340078 */3、将815位置1。unsigned int a, b, mask = 0x0000ff00;a = 0x12345678;b = a | mask; /* 0x1234ff78 */习题 1、统计一个无符号整数的二进制表示中1的个数,函数原型是int countbit(unsigned int x);。2、用位操作实现无符号整数的乘法运算,函数原型是unsigned int multiply(unsigned int x, unsigned int y);。例如:(11011)2(10010)2=(11011)21)+(11011)24)。3、对一个32位无符号整数做循环右移,函数原型是unsigned int rotate_right(unsigned int x, int n);。所谓循环右移就是把低位移出去的部分再补到高位上去,例如rotate_right(0xdeadbeef, 8)的值应该是0xefdeadbe。1.4.异或运算的一些特性 1、一个数和自己做异或的结果是0。如果需要一个常数0,x86平台的编译器可能会生成这样的指令:xorl %eax, %eax。不管eax寄存器里的值原来是多少,做异或运算都能得到0,这条指令比同样效果的movl $0, %eax指令快,直接对寄存器做位运算比生成一个立即数再传送到寄存器要快一些。2、从异或的真值表可以看出,不管是0还是1,和0做异或保持原值不变,和1做异或得到原值的相反值。可以利用这个特性配合掩码实现某些位的翻转,例如:unsigned int a, b, mask = 1U 6;a = 0x12345678;b = a mask; /* flip the 6th bit */3、如果a1 a2 a3 . an的结果是1,则表示a1、a2、a3.an之中1的个数为奇数个,否则为偶数个。这条性质可用于奇偶校验(Parity Check),比如在串口通信过程中,每个字节的数据都计算一个校验位,数据和校验位一起发送出去,这样接收方可以根据校验位粗略地判断接收到的数据是否有误。4、x x y = y,因为x x = 0,0 y = y。这个性质有什么用呢?我们来看这样一个问题:交换两个变量的值,不得借助额外的存储空间,所以就不能采用temp = a; a = b; b = temp;的办法了。利用位运算可以这样做交换:a = a b;b = b a;a = a b;分析一下这个

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论