01 | 位运算按位取反
程序中所有的数在计算机内存中都是以二进制的形式存储。二进制在内存中又是以补码的形式存放。位运算对 CPU 比较友好,是一种程序优化的手段。 位运算有:
- 取反 ~
- 按位或 |
- 按位异或 ^
- 按位与 &
对于比特位(bit)还可以进行移位:
- 左移运算:向左进行移位操作,高位丢弃,低位补 0.
- 右移运算:向右进行移位操作,对无符号数,高位补 0;对于有符号位,最高位补符号位
在 C/C++中一个 char 变量占 1 个字节,即 8 个bit,其实每一个 bit 都可以当前一个开关来用,以此来做标志位。
#
1. 基础位运算:#
1.1 按位与 &两个位都是 1,结果才会 1,否则为 0,例如:
0000 1001& 1001 1010------------- 0000 1000
#
1.2 按位或 |两个位都是 0 时,结果才会 0,否则为 1,例如:
0000 1001| 1001 1010------------- 1001 1011
#
1.3 按位或 |两个维护都是 0 时,结果才会 0,否则为 1,例如:
0000 1001^ 1001 1010------------- 1001 1011
#
1.4 取反 ~0 变 1,1 变 0
~ 1001 1010------------- 0110 0101
#
1.5 左移运算 <<向左进行移位操作,高位丢弃,低位补 0。例如:
int a = 8a << 3移位前 0000 0000 0000 0000 0000 1000移位后 0000 0000 0000 0000 0100 0000
#
1.6 右移运算 >>向右进行移位操作,对无符号数,高位补 0,对于有符号数,高位补符号位。例如:
unsigned int a = 8a >> 3移位前 0000 0000 0000 0000 0000 1000移位后 0000 0000 0000 0000 0000 0001 int a = -8a >> 3 移位前 1111 1111 1111 1111 1111 1000移位后 1111 1111 1111 1111 1111 1111
#
2. 按位取反
首先要搞懂原码、补码、反码、取反。
- 原码:10 进制变 2 进制,8 位。
- 正数是二进制本身
- 负数是符号位 1,数值部分去 X 绝对值的二进制。并标明符号位。
- 最左一位为最高位,代表符号位。
- 反码:取反
- 正数的反码和补码相同
- 负数的符号位为 1,其他位是原码取反
- 补码:符号为不变,其他位取反
- 正数的补码和原码、反码相同
- 负数是符号位为 1,其他位是原码取反,末尾+1。或者说负数的补码是其绝对值反码未位加 1
- 取反即使 0 变 1,1 变 0
为什么要有补码及其补码修复?因为计算机中减法是通过加一个负数处理的,而负数又是通过补码保存的。目的就是为了统一加法减法。 二进制在内存中的存放是以补码的形式存放的,
示例一: 正数 9
原码 0000 1001 反码 0000 1001 补码 0000 1001 取反 1111 0110 符号位一起取反,这里是补码的取反 反码 1000 1001 符号位不变,其余各位取反 补码 1000 1010 负数的补码就是反码的末尾+1
最终结果是 1000 1010,最高位 1 代表负数,1010 = 10,所以最终结果-10
正数 5
原码 0000 0101反码 0000 0101补码 0000 0101取反 1111 1010 符号位一起取反,这里是补码的取反反码 1000 0101 符号位不变,其余各位取反补码 1000 0110 负数的补码就是反码的末尾+1
最终结果是 1000 0110,最高位 1 代表负数,0110 = 6,所以最终结果-6
负数 9
原码 1000 1001反码 1111 0110补码 1111 0111取反 0000 1000 符号位一起取反,这里是补码的取反反码 0000 1000 正数的反码、补码、原码相同补码 0000 1000 正数的补码、反码相同
最终结果是 0000 1000,最高位 0 代表正数,1000 = 8,所以最终结果8
负数-10
原码 1000 1010反码 1111 0101补码 1111 0110取反 0000 1001 符号位一起取反,这里是补码的取反反码 0000 1001 正数的反码、补码、原码相同补码 0000 1001 正数的补码、反码相同
最终结果是 0000 1001,最高位 0 代表正数,1001 = 9,所以最终结果9
#
按位取反友趣的事实- 所有正整数的按位取反是其本身+1 的负数。
- 10 按位取反 -11
- 111 按位取反 -112
- 1xxxx11 按位取反 -1xxxx12
- 所有负整数的按位取反是其本身+1 的绝对值。
- -6 按位取反 5
- -111 按位取反 110
- 0 的按位取反是-1。0 在数学界即不是正数也不是负数。