这个位在一个字节中的恢复如何工作?

时间:2017-03-17 20:56:18

标签: c bit-manipulation bitwise-operators bit-shift or-operator

我是编程新手,我发现这种方法可以反转C中字节中的位:

//(10000011) -> (11000001)

unsigned char reverse(unsigned char b) {
   b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
   b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
   b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
   return b;
}

用户在回复this question时发布,但我无法理解它是如何运作的。这些常数意味着什么?

5 个答案:

答案 0 :(得分:5)

查看上述数字的二进制表示可能会有所帮助:

0xF0: 11110000
0x0F: 00001111

0xCC: 11001100
0x33: 00110011

0xAA: 10101010
0x55: 01010101

第一对数字用于屏蔽掉并交换一个字节的前4位和后4位。

第二对屏蔽掉并交换一组4位的前2位和后2位。

第三对屏蔽并交换相邻的位对。

答案 1 :(得分:1)

代码首先交换&#34;半字节&#34;,即具有最低有效4位的最高有效4位。然后它将两个顶部订单对交换在一起,并将底部对一起交换;最后,它成对地交换2n和2n + 1位。

我将在尖括号中用它们的指数来表示b这里的原始值的位(这只是我在这里使用的伪符号,不正确C);我使用o来标记始终为0的任何位。所以一开始我们有

<76543210>

在第一次操作中没有

  • <76543210> & 0xF0 - &gt; <7654oooo>
  • <76543210> & 0x0F - &gt; <oooo3210>

现在前者右移4位,后者左移4,因此我们得到

  • <7654oooo> >> 4 - &gt; <oooo7654>
  • <oooo3210> << 4 - &gt; <3210oooo>

最后这些是或者在一起,因此在声明之后

b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;

b的值是原始位的排列<32107654>

在第二个语句中,掩码0xCC11001100二进制,0x3300110011二进制;中间值是:

  • (<32107654> & 0xCC) >> 2 - &gt; <32oo76oo> >> 2 - &gt; <oo32oo76>;和
  • (<32107654> & 0x33) << 2 - &gt; <oo10oo54> << 2 - &gt; <10oo54oo>

这些2或“一起”将导致排列<10325476>。最后,掩码0xAA为二进制101010100x5501010101。因此我们有

  • (<10325476> & 0xAA) >> 1 - &gt; <1o3o5o7o> >> 1 - &gt; <o1o3o5o7>;和
  • (<10325476> & 0x55) << 1 - &gt; <o0o2o4o6> << 1 - &gt; <0o2o4o6o>

这些或“一起”将导致排列<01234567>,这与原始排列相反。

答案 2 :(得分:1)

所以这只是一点点转移。这些位按以下顺序排列:

76543210

现在,第一行,第一部分保持高位,将低位设置为0(掩码为0b11110000),将它们向右移动4。第二部分对低位(掩码为0b00001111)执行相同操作,并向左移位:

first line, first part:  7654xxxx => xxxx7654 (bits shift to the right)
first line, second part: xxxx3210 => 3210xxxx (bits shift to the left)
add them together:                => 32107654

然后,第二行。相同的操作,不同的掩码(分别为0b11001100和0b00110011),32107654

second line, first part:  32xx76xx => xx32xx76 (bits shift to the right)
second line, second part: xx10xx54 => 10xx54xx (bits shift to the left)
add them together:                 => 10325476

第三行与其他掩码相同(分别为0b10101010和0b01010101),10325476

third line, first part:  1x3x5x7x => x1x3x5x7 (bits shift to the right)
third line, second part: x0x2x4x6 => 0x2x4x6x (bits shift to the left)
add them together:                => 01234567

最后,我们最终采取行动:

76543210 => 01234567

答案 3 :(得分:0)

让我们对b中的位进行编号,如下所示:

01234567
二进制文件中的

0xF0111100000x0F00001111。第一个赋值将最左边的4位向右移动,最右边的4位向左移动,然后将它们与OR组合,结果是:

45670123

0xCC110011000x3300110011。当这些屏蔽位移位2位并组合时,结果为:

67452301

最后,0xAA101010100x5501010101。完成这些掩码和移位后,结果为:

76543210

瞧!这是相反的顺序。

注意,对于每对移位,位掩码是彼此相反的,并且移位的位数与掩码中1位序列的长度相同。因此,它们中的每一个都交换了一组大小为序列长度的位。

答案 4 :(得分:0)

您需要了解4个主要内容才能理解上述代码的含义。

  1. & (AND) Bitwise Operator.
  2. | (OR) Bitwise Operator.
  3. >> (Right Shift Operator).
  4. << (Left Shift Operator).
  5. 幸运的是,我刚写了一篇详细的博客,解释了Number System and Bit Manipulation

    的所有内容