在进行按位操作前,应当熟悉十六进制数和二进制数的简易转换
四位权值法(4位分组法)转换二进制到十六进制
步骤:
- 将二进制数按四位分组:
- 从右往左,每四位一组。如果二进制数的位数不满足四位的倍数,可以在最左边补充零。
- 计算每组四位二进制数的十六进制值:
- 每组四位二进制数对应的权值是
8, 4, 2, 1
,分别对应从左到右的四个位。 - 计算每一组的十进制值:
十进制值 = (最左位 * 8) + (次左位 * 4) + (次右位 * 2) + (最右位 * 1)
- 每组四位二进制数对应的权值是
- 将每组的十进制值转换为十六进制:
- 得到的十进制值直接对应十六进制数,如果十进制值大于等于10,使用字母A-F表示。
- 拼接每组的十六进制数:
- 最后将所有转换得到的十六进制数拼接起来,形成完整的十六进制表示。
例 1:二进制 101101
转换为十六进制
- 按四位分组:
101101
→10 1101
- 补零:
0010 1101
- 计算每组十六进制值:
- 第一组
0010
:0 * 8 + 0 * 4 + 1 * 2 + 0 * 1 = 2
→ 十六进制为2
- 第二组
1101
:1 * 8 + 1 * 4 + 0 * 2 + 1 * 1 = 8 + 4 + 1 = 13
→ 十六进制为D
- 第一组
- 拼接结果:
- 十六进制结果为
0x2D
- 十六进制结果为
例 2:二进制 10101011
转换为十六进制
- 按四位分组:
10101011
→1010 1011
- 计算每组十六进制值:
- 第一组
1010
:1 * 8 + 0 * 4 + 1 * 2 + 0 * 1 = 8 + 2 = 10
→ 十六进制为A
- 第二组
1011
:1 * 8 + 0 * 4 + 1 * 2 + 1 * 1 = 8 + 2 + 1 = 11
→ 十六进制为B
- 第一组
- 拼接结果:
- 十六进制结果为
0xAB
- 十六进制结果为
在C语言中,移位操作(Shift Operations)指的是通过操作符将二进制数的位向左或向右移动。移位操作常用于高效的数值计算、位操作和硬件编程中。
1.移位操作符
- 左移操作符 (
<<
):将数值的二进制位向左移动指定的位数,左移时高位丢弃,低位补零。- 例如:
a << n
,表示将a
的二进制位左移n
位。
- 例如:
- 右移操作符 (
>>
):将数值的二进制位向右移动指定的位数,右移时,符号位(对于有符号数)通常会被扩展,高位补符号位(对于无符号数补零)。- 例如:
a >> n
,表示将a
的二进制位右移n
位。
- 例如:
例:以 0x123
为例
假设我们有一个十六进制数 0x123
,其二进制表示为:
0x123 = 0001 0010 0011 (二进制)
左移操作:<<
- 左移 1 位:
0x123 << 1
- 计算:二进制
0001 0010 0011
左移 1 位,结果是0010 0100 0110
。 - 十六进制表示:
0x246
。 - 解释:左移 1 位相当于将数字乘以 2。
0x123 << 1 = 0x246
- 计算:二进制
- 左移 2 位:
0x123 << 2
- 计算:二进制
0001 0010 0011
左移 2 位,结果是0100 1000 1100
。 - 十六进制表示:
0x48C
。 - 解释:左移 2 位相当于将数字乘以 4。
0x123 << 2 = 0x48C
- 计算:二进制
- 左移 4 位:
0x123 << 4
- 计算:二进制
0001 0010 0011
左移 4 位,结果是0001 0010 0011 0000
。 - 十六进制表示:
0x1230
- 解释:左移 4 位相当于将数字乘以 16。
0x123 << 4 = 0x1230
- 计算:二进制
右移操作:>>
- 右移 1 位:
0x123 >> 1
- 计算:二进制
0001 0010 0011
右移 1 位,结果是0000 1001 0001
。 - 十六进制表示:
0x91
。 - 解释:右移 1 位相当于将数字除以 2。
0x123 >> 1 = 0x91
- 计算:二进制
- 右移 2 位:
0x123 >> 2
- 计算:二进制
0001 0010 0011
右移 2 位,结果是0000 0100 1000
。 - 十六进制表示:
0x48
。 - 解释:右移 2 位相当于将数字除以 4。
0x123 >> 2 = 0x48
- 计算:二进制
- 右移 4 位:
0x123 >> 4
- 计算:二进制
0001 0010 0011
右移 4 位,结果是0001 0010
。十六进制表示:0x12
。解释:右移 4 位相当于将数字除以 16。
0x123 >> 4 = 0x012
- 计算:二进制
2. 取反操作(~
)
取反操作将二进制数的每一位反转,即 0 变成 1,1 变成 0。
例子:~0x123
- 原始值
0x123
对应的二进制是:0x123 = 0001 0010 0011 (二进制)
- 取反:
~0x123 = 1110 1101 1100 (二进制)
- 计算结果:
- 取反后的二进制值是
1110 1101 1100
。 - 这是
0xEDC
的十六进制表示。
- 取反后的二进制值是
所以,~0x123
的结果是 0xEDC
。
3. 位与操作(&
)
位与操作会逐位比较两个操作数的二进制位,只有当两个对应位都是 1 时,结果位才为 1,否则为 0。
例子:0x123 & 0xFF
原始值:
0x123
的二进制是:0001 0010 0011
。
0xFF
的二进制是:1111 1111
(即全 8 位 1)。
位与操作
0x123 & 0xFF = 0001 0010 0011
& 0000 1111 1111
-----------------------
= 0000 0010 0011
计算结果:
结果的二进制是 0010 0011
,十六进制是 0x23
。
4. 位或操作(|
)
位或操作会逐位比较两个操作数的二进制位,只要两个对应位中有一个是 1,结果位就为 1。
例子:0x123 | 0xFF
原始值:
0x123
的二进制是:0001 0010 0011
。
0xFF
的二进制是:1111 1111
。
位或操作:
0x123 | 0xFF = 0001 0010 0011
| 0000 1111 1111
-----------------------
= 0001 1111 1111
计算结果:
结果的二进制是 1111 1111
,十六进制是 0x1FF
。
置位(Set)和清位(Clear)是位操作中常见的操作,它们主要用来修改某一特定位置的值,通常用于控制寄存器或位域,或者在一些算法中进行标记。
5. 置位操作(Set)
置位操作的目的是将某一特定位置的位设置为 1,通常用于激活某个标志位或开启某个功能。
位(bit)是从第0位开始。
置位操作的常见方法:
- 使用 按位或(
|
) 操作符。
示例:
假设我们有一个变量 x
和一个掩码 mask
,我们想要将 x
的第 n
位置为 1,可以使用如下操作:
x = x | (1 << n);
1 << n
:将 1 向左移动n
位,生成一个只有第n
位为 1 的掩码。x | (1 << n)
:将x
和这个掩码按位“或”运算,确保第n
位为 1。
例子:
unsigned int x = 0x123; // 二进制为 0001 0010 0011
x = x | (1 << 7); // 置第 7 位为 1
1 << 7
会生成 1000 0000
,与 x
进行位或操作:
0001 0010 0011 (0x123)
| 0000 1000 0000
------------
0001 1010 0011 (结果 0x1A3)
所以,置位操作后,x
的值变成了 0x1A3
。
6. 清位操作(Clear)
清位操作的目的是将某一特定位置的位设置为 0,通常用于关闭某个标志位或禁用某个功能。
清位操作的常见方法:
- 使用 按位与(
&
) 操作符,并将目标位置的掩码取反。
掩码(Mask)在计算机科学中,尤其是位操作中,指的是一个二进制数,用来操作另一个二进制数的特定位。掩码通常用于 选择 或 修改 特定的位。通过与目标数进行按位与、按位或、按位异或等运算,掩码可以帮助我们从数值中提取特定位,或者设置、清除特定的位。
示例:
假设我们有一个变量 x
和一个掩码 mask
,我们想要将 x
的第 n
位清零,可以使用如下操作:
x = x & ~(1 << n);
1 << n
:将 1 向左移动n
位,生成一个只有第n
位为 1 的掩码。~(1 << n)
:对该掩码取反,生成一个只有第n
位为 0 其余为 1 的掩码。x & ~(1 << n)
:将x
和这个掩码按位“与”运算,确保第n
位为 0。
例子:
unsigned int x = 0x123; // 二进制为 0001 0010 0011
x = x & ~(1 << 7); // 清第 7 位为 0
1 << 7
会生成 1000 0000
,取反后得到 0111 1111
。
x & 0111 1111
结果是:
0001 0010 0011 (0x123)
& 1111 0111 1111
------------
0001 0010 0011 (结果 0x123)
此例中,虽然我们试图清除第 7 位,但 x
原本并没有在第 7 位设置为 1,因此操作结果没有变化。
总结
- 左移 (
<<
) 会将数值乘以 2 的幂次方。 - 右移 (
>>
) 会将数值除以 2 的幂次方(对于整数)。 - 对于 无符号数,左移和右移不会出现符号位扩展问题,结果只是单纯的位移。
- 对于 有符号数,右移时符号位会扩展,保持符号正确。
- 取反(
~
):将二进制数的每一位反转,~0x123
结果为0xEDC
。 - 位与(
&
):只有对应位都为 1 时结果才为 1,0x123 & 0xFF
结果为0x03
。 - 位或(
|
):只要对应位有一个是 1 结果就是 1,0x123 | 0xFF
结果为0xFF
。 - 置位操作:通过按位或(
|
)将目标位设置为 1,常用于激活或开启某个功能。 - 清位操作:通过按位与(
&
)并取反掩码将目标位设置为 0,常用于关闭或禁用某个功能。