一 . 位运算简介
首先看下Wiki百科对位运算的定义:
位运算是一种通过算法来处理比特或比词短的数据片段的操作。需要位运算的计算机程序任务包括低级设备控制、错误检测和校正算法、数据压缩、加密算法和优化。对于大多数其他任务,现代程序语言允许编程者直接在抽象层面上工作,而不是去操作那些抽象的比特位(即我们现在编程都是用代码写程序,而不是0和1)。在某些情况下,位运算可以避免或者减少在一个数据结构上需要进行循环的次数,并且可以成倍的提升效率,因为位运算是并行处理的,但是缺点是位运算的代码比较难以编写及维护。
二 . 位运算规则
在C/C++中可以用的位运算包括:AND、OR、XOR、NOT和位移。
A . AND与运算
与运算操作符为&,其运算规则为:
操作数一 | 操作数二 | RESULT |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
B . OR或运算
或运算操作符为|,其运算规则为:
操作数一 | 操作数二 | RESULT |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
C . XOR异或运算
异或运算操作符为^,其运算规则为:
操作数一 | 操作数二 | RESULT |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
D . NOT取反运算
取反运算操作符为~,其运算规则为:
操作数 | RESULT |
---|---|
0 | 1 |
1 | 0 |
注意事项:
由于在计算机中,二进制的存储形式为补码形式,事实上,计算机中有且仅有补码一种码,而我们所说的原码、反码都是所定义出的为了与补码形成转换关系的格式。正数的原码、反码、补码都是其本身,负数的原码最高位符号位为1,反码除符号位外取反,补码在反码基础上加一得到。例如,正整数5的原码、反码、补码都为0x00000101,对5取反就有0x11111010,由于这是补码表示,转换为反码是0x11111001,转换为原码是0x10000110,即-6为对5取反后的值。
E . 位移运算
位移运算包括左移(<<)与右移(>>),其运算规则为:
当进行左移操作时,若高位溢出则舍弃,低位空出用0填补;当进行右移操作时,若低位溢出则舍弃,高位空出,正数用0填补,负数用1填补。
三 . 位运算技巧
A . AND与运算技巧
1 . 清零
如果想将一个指定单元清零,可以通过&0实现,即:
int num = 1; /* Clear the num. */
int res = num & 0; /* Now num is zero. */
2 . 取指定二进制位
如果想取某一个数的指定二进制位,可以通过&1操作实现,例如要保存最低两位的二进制位:
int num = 10; /* num = 00001010 */
int res = num & 3; /* 3 = 00000011 res = 00000010 */
3 . 判断奇偶性
如果想要判断一个数的奇偶性,可以利用其最低位是0还是1来判断:
int num = 10; /* num = 00001010 */
if((num & 1) == 0) printf("这是偶数!");
4 . 判断是否为2的次方
如果需要判断一个数是否为2的次方数,那么只要该数的二进制形式中1的个数为1:
int num = 8; /* num = 00001000 */
if(num