赞
踩
1-位运算符
基于二进制位的运算,一定要从二进制角度和补码角度出发考虑
~ 按位取反,每一位二进制 0 变 1, 1 变 0,
对于int i = 1; ~i的结果?
1的原码和补码为0000 0000 0000 0000 0000 0000 0000 0001
取反其补码为 1111 1111 1111 1111 1111 1111 1111 1110
则~1原码为 1000 0000 0000 0000 0000 0000 0000 0010
所以 ~1 = -2
& 按位与 有一位为0,则结果为0,同交集
12 & 5的结果?
12的原码(补码)0000 0000 0000 0000 0000 0000 0000 1100
5的原码(补码) 0000 0000 0000 0000 0000 0000 0000 0101
12 & 5的结果 0000 0000 0000 0000 0000 0000 0000 0100
所以 12 & 5 = 4
| 按位或 有一位为1 ,则结果为1 ,同并集
12 | 5的结果?
12的原码(补码)0000 0000 0000 0000 0000 0000 0000 1100
5的原码(补码) 0000 0000 0000 0000 0000 0000 0000 0101
12 | 5的结果 0000 0000 0000 0000 0000 0000 0000 1101
所以 12 | 5 = 13
^ 按位异或 位相异为1,相同为0
12 ^ 5的结果?
12的原码(补码)0000 0000 0000 0000 0000 0000 0000 1100
5的原码(补码) 0000 0000 0000 0000 0000 0000 0000 0101
12 ^ 5的结果 0000 0000 0000 0000 0000 0000 0000 1001
所以 12 ^ 5 = 9
对于位运算优先级:位运算优先级较低,建议使用括号确保正确使用
2-左移,右移运算
右移 >>时,右移n位 则最后面n位消失,前面的每一位依次向后移动n位,缺失的高位需要补上,无符号数均补0,有符号数最高位补n个符号位,右移补n个符号位是为了不改变原数值正负
0100 1100 >>1位 0010 0110
0100 1100 >>2位 0001 0011
0100 1100 >>3位 0000 1001
1011 0100 >>2位 1110 1101
左移 <<时,左移n位 则最前面n位消失,剩下的位向前移动n位,缺失的低位需要用0补上,左移时,无论最高位是什么,都会消失,可能改变原数值正负
1011 0100 <<1位 0110 1000
3-位运算技巧
1,关于按位与运算
假设有一个数,现在需要取这个数所对应的二进制的后三位
如 int num = 0x9A 即0000 0000 0000 0000 0000 0000 1001 1010
令num & 7
0000 0000 0000 0000 0000 0000 1001 1010
0000 0000 0000 0000 0000 0000 0000 0111
num & 7的结果就是 0000 0000 0000 0000 0000 0000 0000 0010 这样就取出了后三位
进一步思考,对于num % 8就是 num所对应的二进制的后三位
结论 num % 8 <=> num & 7
用num & 7来代替num % 8是为了加快计算机运算速度,计算机的运算分为两类,有逻辑运算和算数运算,位运算属于逻辑运算速度很快,而加减运算的电路要用到 全加器 才可实现,其速度比1位运算要低,乘除的速度更低,如果将乘除换成位运算,可以提高速度
2,关于异或运算
通过异或的特性,可以用异或运算对数字加密
明文:0100 1101
密钥:1011 1100
异或加密…
密文:1111 0001
密钥:1011 1100
异或解密…
明文:0100 1101
用异或进行 局部按位取反
结论: A ^ 0 <=> A
A ^ 1 <=> !A
对于 num(unsigned char)为 xxxx xxxx 位的标号位 b0b1b2b3 b4b5b6b7
希望对 b4b5b6这三位按位取反,其他位保持不变
要实现此要求,则, b0b1b2b3 b4b5b6b7 和 0000 1110 异或运算,就可部分取反
3,设置某一个位为0或1
设置某一个位为1,称为 置位
设置某一个位为0,称为 清位
被设置的某一个位的范围在一个字节内,即在b0-b7的范围
xxxx xxxx 位的标号位 b0b1b2b3 b4b5b6b7
置位:xxxx xxxx 将这个字节的21第7位,即最末位置1,其它位不变
xxxx xxxx 和 0000 0001 或运算
则xxxx xxxx | 0000 0001 结果为 xxxx xxx1 完成了最后一位置1
现在要求实现一个操作:已知num和i,num表示一个字节数值,i表示从左向右这个字节的第i位
i的取值从0-7,要求将num的第i位置位
结论: num | (1 << (7 - i)) 其中 7-i可以用i ^ 7代替
#define SET(num, i) ( (num) | ( 1 << ( ( i ) ^ 7) ) ) 这个宏可以把num的第i位 置位为1
num不动,将0000 0001中的1移动到i,进行 num | 移动后结果
清位:为了将num的第i位置0
#define CLR(num, i) ( (num) & ~( 1 << ( ( i ) ^ 7) ) ) 这个宏可以把num的第i位 清位为0
num不动,将1111 1110 中的0移动到i,进行 num & 移动后结果
4,取出一个字节n的值的从左向右的第i位上的值
#define GET(num, i) ( ( (n) >> ( ( i ) ^ 7 ) ) & 1)
将所需要取出位移动到最低位(最右),进行 1 & 移动后结果,完成后,除了最低为,其它位均为0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。