位运算的规则都基于内存中的二进制形式,因此负数参与运算时取的是补码;同时还要注意有符号与无符号类型的区别。

按位与 & (and)

两位都为 1 结果才是 1,其余情况都为 0。

都为1才为1,其余为0
                二进制001 & 101 = 001
                十进制1&-1=1  , 00000001 &1

按位或 | (or)

两位中只要有一个为 1,结果就是 1;只有两位都为 0 时结果才是 0。

有一个为1就为1,都为0才为0
                二进制001|011=011;
                十进制1|-1=-1 , 00000001 |

按位异或 ^ (xor)

两位相同结果为 0,两位不同结果为 1。需要特别注意的是,异或在底层是以补码参与运算的,用原码来推结果会得到错误答案。

相同为0,不同为1
                二进制010 ^ 011 = 001
                十进制 1^-1 =-2 ,00000001 ^
                原码
                00000001
                10000001
                10000000//明显结果不对
                补码
                00000001
                11111111
                11111110  =-2//所以运算时是补码参与运算 而不是原码

按位取反 ~ (not)

对二进制的每一位取反,0 变 1、1 变 0。

二进制位取反
                二进制 ~011 = 100
                十进制 ~1 =2
                000000001
                111111110
                
                十进制~-1=0
                111111111
                000000000

应用示例:不借助中间变量交换两个数

利用异或的自反性,可以在不引入临时变量的前提下交换 a 和 b。实际时间效率和常规的 swap 差不多,更多是一种技巧性的写法。

a=a^b;
                b=a^b;
                a=a^b;//时间效率和常规swap差不多,