二进制位运算

总结几个位运算的用法

下面举的例子中,a=1010 1010

按位与&

(1)清零:a&0=0

(2)取指定位上的数字,如取得数字a的最后四位:a&0000 1111 = 0000 1010

按位或|

(1)对某些位置置为1,如将a的后四位置为1:a|0000 1111 = 1010 1111

异或^

(1)将某些位置取反,如将a的后四位取反:a^0000 1111 = 1010 0101
1加0,0加1都等于1,而0加0,1加1等于0
(2)与0异或保留原值,如:a^0000 0000 =1010 1010

(3)交换两个的变量值:A=A^B; B=A^B; A=A^B; 可以完成A和B的交换。

左移

1的2进制是000…0001
左移2位之后变成 000…0100,也就是10进制的4,左移1位相当于乘以2,那么左移n位就是乘以2的n次方了((有符号数不完全适用,因为左移有可能导致符号变化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

需要注意的一个问题是int类型最左端的符号位和移位移出去的情况.我们知道,int是有符号的整形数,最左端的1位是符号位,即0正1负,那么移位的时候就会出现溢出,例如:

int i = 0x40000000; //16进制的40000000,为2进制的01000000...0000
i = i << 1;

那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000...0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出.如果再接着把i左移1位会出现什么情况呢?在C语言中采用了丢弃最高位的处理方法,丢弃了1之后,i的值变成了0.

左移里一个比较特殊的情况是当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位,如:

int i = 1, j = 0x80000000; //设int为32位
i = i << 33; // 33 % 32 = 1 左移1位,i变成2
j = j << 33; // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃

在用gcc编译这段程序的时候编译器会给出一个warning,说左移位数>=类型长度.那么实际上i,j移动的就是1位,也就是33%32后的余数.在gcc下是这个规则,别的编译器是不是都一样现在还不清楚.

总之左移就是: 丢弃最高位,0补最低位

右移

除以2

口诀:

  清零取数要用与,某位置一可用或

  若要取反和交换,轻轻松松用异或