为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

什么是按位或

2017-10-23 7页 doc 40KB 23阅读

用户头像

is_314871

暂无简介

举报
什么是按位或什么是按位或 什么是按位或,什么是按位异或,什么是按位与 & 按位与, | 按位或 , ^ 按位异或 AND (位与&) OR ( 位或| ) XOR ( 位异或^ ) 1 & 1 = 1 1 | 1 = 1 1 ^ 1 = 0 1 & 0 = 0 1 | 0 = 1 1 ^ 0 = 1 0 & 1 = 0 0 | 1 = 1 0 ^ 1 = 1 0 & 0 = 0 0 | 0 = 0 0 ^ 0 = 0 1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二...
什么是按位或
什么是按位或 什么是按位或,什么是按位异或,什么是按位与 & 按位与, | 按位或 , ^ 按位异或 AND (位与&) OR ( 位或| ) XOR ( 位异或^ ) 1 & 1 = 1 1 | 1 = 1 1 ^ 1 = 0 1 & 0 = 0 1 | 0 = 1 1 ^ 0 = 1 0 & 1 = 0 0 | 1 = 1 0 ^ 1 = 1 0 & 0 = 0 0 | 0 = 0 0 ^ 0 = 0 1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二 进位均为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=%d\nb=%d\nc=%d\n",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=%d\nb=%d\nc=%d\n",a,b,c); } 3. 按位异或运算 按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应 的二进位相异时,结果为1。参与运算数仍以补码出现,例如9^5可写成算式如下: 00001001^00000101 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),unsigned char c = 0xfc; ~运算符也要做Integer Promotion,所以在C语言中其实并不存在8位整数的位运算,操作数在 unsigned int i = ~c; 做位运算之前都至少被提升为int型了,上面用8位整数举例只是为了书写方便。比如: 计算过程是这样的:常量0xfc是int型的,赋给c要转成unsigned char,值不变;c的十六进制表示是fc,计算~c时先提升为整型(000000fc)然后取反,最后结果是ffffff03。注意,如果把~c看成是8位整数的取反,最后结果就得3了,这就错了。为了避免出错,一是尽量避免不同类型 之间的赋值,二是每一步计算都要按上一章讲的类型转换仔细检查。 1.2. 移位运算符(Bitwise Shift)包括左移<<和右移>>。左移将一个整数的各二进制位全部左移若干位, 例如0xcfffffff3<<2得到0x3fffffcc: 16.2. 最高两位的11被移出去了,最低两位又补了两个0,其它位依次左移两位。但要注意,移动的位 数必须小于左操作数的总位数,比如上面的例子,左边是unsigned int型,如果左移的位数大于等于32位,则结果是Undefined。移位运算符不同于+ - * / ==等运算符,两边操作数的类型不要 求一致,但两边操作数都要做Integer Promotion,整个表达式的类型和左操作数提升后的类型相 同。 12。比如二进制11(十进制3)左移一位变成110,就是6,再左移一位变成1100,就是12。读者可以自己验证这条规律对有符号数和无 符号数都成立,对负数也成立。当然,如果左移改变了最高位(符号位),那么结果肯定不是乘以 2了,所以我加了个前提“在一定的取值范围内”。由于计算机做移位比做乘法快得多,编译器可 以利用这一点做优化,比如看到源代码中有i * 8,可以编译成移位指令而不是乘法指令。 当操作数是无符号数时,右移运算的规则和左移类似,例如0xcfffffff3>>2得到0x33fffffc: 16.3. 最低两位的11被移出去了,最高两位又补了两个0,其它位依次右移两位。和左移类似,移动的 位数也必须小于左操作数的总位数,否则结果是Undefined。在一定的取值范围内,将一个整数右 移1位相当于除以2,小数部分截掉。 当操作数是有符号数时,右移运算的规则比较复杂: , 如果是正数,那么高位移入0 , 如果是负数,那么高位移入1还是0不一定,这是Implementation-defined的。对于 x86平台的gcc编译器,最高位移入1,也就是仍保持负数的符号位,这种处理方式 对负数仍然保持了“右移1位相当于除以2”的性质。 综上所述,由于类型转换和移位等问题,用有符号数做位运算是很不方便的,所以, 。 int i = 0xcffffff3; 1、下面两行printf打印的结果有何不同?请读者比较分析一下。%x转换说明的含义详见第 2.9 节 printf("%x\n", 0xcffffff3>>2); “格式化I/O函数”。 printf("%x\n", i>>2); 1.3. 如果要对一个整数中的某些位进行操作,怎样表示这些位在整数中的位置呢?可以用掩码(Mask) 来表示。比如掩码0x0000ff00表示对一个32位整数的8~15位进行操作,举例如下。 1、取出8~15位。 unsigned int a, b, mask = 0x0000ff00; a = 0x12345678; b = (a & mask) >> 8; /* 0x00000056 */ 这样也可以达到同样的效果: b = (a >> 8) & ~(~0U << 8); 2、将8~15位清0。 unsigned int a, b, mask = 0x0000ff00; a = 0x12345678; b = a & ~mask; /* 0x12340078 */ 3、将8~15位置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)×(10010)=((11011)<<1)+((11011)<<4)。 2222 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、如果a ^ a ^ a ^ ... ^ a的结果是1,则表示a、a、a...a之中1的个数为奇数个,否则为123n123n 偶数个。这条性质可用于奇偶校验(Parity Check),比如在串口通信过程中,每个字节的数据都 计算一个校验位,数据和校验位一起发送出去,这样接收方可以根据校验位粗略地判断接收到的数 据是否有误。 a = a ^ b; 4、x ^ x ^ y == y,因为x ^ x == 0,0 ^ y == y。这个性质有什么用呢?我们来看这样一个问题: 交换两个变量的值,不得借助额外的存储空间,所以就不能采用temp = a; a = b; b = temp;的b = b ^ a; 办法了。利用位运算可以这样做交换: a = a ^ b; 分析一下这个过程。为了避免混淆,把a和b的初值分别记为a和b。第一行,a = a ^ b;第0000二行,把a的新值代入,得到b = b ^ a ^ b,等号右边的b相当于上面公式中的x,a相当于00000y,所以结果为a;第三行,把a和b的新值代入,得到a = a ^ b ^ a,结果为b。注意这个00000过程不能把同一个变量自己跟自己交换,而利用中间变量temp则可以交换。
/
本文档为【什么是按位或】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索