2017-03-17 35 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