2017-03-17 90 views
1

我新的编程,我发现这个方法来扭转字节位在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,但我不明白它是如何工作的。这些常数是什么意思?

+0

转换常数为二进制看什么他们的意思。 – Barmar

+1

这会互换4位组,然后是2,然后是1.首先,7654与3210.然后,7632与5410.然后,7531与6420.只是写这让我意识到,要解释它并不容易指点:P – AntonH

+0

逐句通过调试器中的函数,在每个语句后以二进制格式打印'b'。你将会开悟。 – Barmar

回答

1

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


我会通过自己的指数表示的b这里原始值的位,在尖括号(这只是一个伪符号,我在这里使用,不正确C);我使用o来标记任何总是0的位。所以,在开始的时候,我们有

<> 

没有在第一操作中,我们有

  • <> & 0xF0 - ><7654oooo>
  • <> & 0x0F - ><oooo3210>

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

  • <7654oooo> >> 4 - ><oooo7654>
  • <oooo3210> << 4 - ><3210oooo>

最后,这些中作或运算在一起,因此该语句

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

后的b值的置换<32107654>原始位。

在第二条语句掩模0xCC是二进制11001100,并0x33是二进制00110011;中间值是:

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

这两个or'ed在一起将导致排列<10325476>。现在最后,掩码0xAA10101010二进制,而0x5501010101。因此,我们有

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

这些或运算一起将导致排列<>这是原始的反向。

5

这可能有助于看看上面的数字的二进制表示:

0xF0: 11110000 
0x0F: 00001111 

0xCC: 11001100 
0x33: 00110011 

0xAA: 10101010 
0x55: 01010101 

第一对数字被用来屏蔽掉与交换前4位和字节的最后4位。

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

第三对遮蔽并交换相邻位对。

1

所以它只是很多位移。的比特是按照以下顺序:


现在,第一行中,第一部分保持高比特,设定较低位为0(掩模是0b11110000),转移他们4到右侧。第二部分确实对于较低的位(掩模是0b00001111),并转移到左侧的相同:

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

然后,第二行。相同的动作,不同的掩模(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:    =>

因此,我们最终,最后,用行动:在b

=>
0

让我们的比特数如下:


二进制0xF011110000,并0x0F00001111。第一分配转移最左边的4位到右侧,最右边的4位到左侧,然后与结合OR它们,所以其结果是:

4567

0xCC11001100,并0x3300110011。当这些屏蔽比特由2个比特移位和组合,其结果是:

67452301 

最后,0xAA101010100x5501010101。当这些掩模和班次完成后,结果为:


瞧!这是相反的顺序。

请注意,对于每对移位,位掩码彼此反转,并且被移位的位数与掩码中1位序列的长度相同。所以他们每个人都交换大小是那个序列长度的比特组。

0

为了理解上面的代码意思,你需要理解4个主要的东西。

  1. & (AND) Bitwise Operator.
  2. | (OR) Bitwise Operator.
  3. >> (Right Shift Operator).
  4. << (Left Shift Operator).

幸运的是,我只是写了一个详细的博客,解释一切有关Number System and Bit Manipulation