十六进制与二进制对应关系
十六进制和二进制之间的转换非常直接,每个十六进制数字直接对应四个二进制位,并且十六进制相对二进制要更加简洁,因此通常书写位操作的代码时会选择使用十六进制来表示数值。
为了方便快速阅读涉及位运算的源码,我们首先需要了解十六进制的 16 个数字和二进制的对应关系,对应关系如下:
- 0对应0000
- 1对应0001
- 2对应0010
- 3对应0011
- 4对应0100
- 5对应0101
- 6对应0110
- 7对应0111
- 8对应1000
- 9对应1001
- A对应1010
- B对应1011
- C对应1100
- D对应1101
- E对应1110
- F对应1111
&
& 按位与(AND)操作。对于每一位,只有两个操作数相对应的位都是1时,结果位才为1,否则为0。
示例:0x1234
& 0x4321
= 0x0220
计算思路:
16进制各位依次转换为二进制,进行二进制对应位计算。
计算演示(从高位到低位):
1: 0001
4: 0100
0000: 0
2: 0010
3: 0011
0010: 2
3: 0011
2: 0010
0010: 2
4: 0100
1: 0001: 0
res: 0x0220
使用 uint16
仅是因为当前示例为 uint16
。
|
| 按位或(OR)操作。对于每一位,如果两个操作数相应的位中至少有一个为1,则结果位为1,否则为0。
示例:0x1234
| 0x4321
= 0x5335
计算思路同 &,简略计算步骤如下:
0x1234
转二进制:0001 0010 0011 0100
0x4321
转二进制:0100 0011 0010 0001
- 对每一位执行或操作:
0001 0010 0011 0100
0100 0011 0010 0001
-------------------
0101 0011 0011 0101
res: 0x5335
^
^ 异或操作(XOR)操作。对于每一位,如果两个操作数对应的位一个为0一个为1,则结果位位1,否则为0。
示例:0x1234
^ 0x4321
= 0x5115
0x1234
转二进制:0001 0010 0011 0100
0x4321
转二进制:0100 0011 0010 0001
- 对每一位执行异或操作:
0001 0010 0011 0100
0100 0011 0010 0001
-------------------
0101 0001 0001 0101
res: 0x5335
&^
&^ 位清除(AND NOT)操作。对于每一位,如果第二操作数相应的位为1,则结果位为0,否则结果位为第一个操作数相应的位。
示例:0x1234
^ 0x4321
= 0x1014
0x1234
转二进制:0001 0010 0011 0100
0x4321
转二进制:0100 0011 0010 0001
- 对每一位执行操作:
0001 0010 0011 0100
0100 0011 0010 0001
-------------------
0001 0000 0001 0101
res: 0x1014
<<
<<
左移操作。将操作数的所有位向左移动指定的位数,右边空出的位用0填充。
示例:0xFFFF
<< 1
= 0xFFFE
0xFFFF
转二进制:1111 1111 1111 1111
- 所有位左移1位,并在末位填充0:
1111 1111 1111 1110
res: 0xFFFE
>>
>>
右移操作。将操作数的所有位向右移动指定的位数,左边空出的位的填充方式取决于操作数的类型(对于无符号数用0填充,对于有符号数,通常用符号位填充,但这可能依赖于具体实现)。
无符号整数示例
0xF0
>> 2
= 0x3C
0xF0
转二进制:1111 0000
- 所有位右移2位:
1111 0000
0011 1100
res: 0x3C
有符号整数示例
对有符号整数求右移我们需要首先知道补码的计算方式
计算补码
以 -16
为例:
- 使用二进制表示正
16
:0001 0000
- 取反(0变1,1变0):
1110 1111
- 加1:
1111 0000
右移
-16
>> 2
= -4
有符号整数:-16(十进制),补码形式为 1111 0000
计算思路:将补码所有位右移2位,高位补符号位(此处为1),得到结果也是补码。
初始:1111 0000
,右移2位:1111 1100
反推十进制整数
将补码 1111 1100
转换为十进制需要:
- 取反:
0000 0011
- 加1得到:
0000 0100
- 转换为十进制:
0000 0100
转为十进制为4
- 加上符号:
-4