2012-09-10 40 views
0

逆向欲反向二進制使用位運算符

unsigned short gf_t = 44 // = 00101100 
在00110100

在C語言無符號短矢量。我如何能夠使用按位運算符?

pdta:我的電腦有32位模式。

+2

[你嘗試過什麼?](http://whathaveyoutried.com)這是功課? – 2012-09-10 19:05:33

+1

在你的例子中,你想得到的結果叫做'交換半字節'。去谷歌上查詢。 – fork0

回答

6

如有疑問,請參閱Bit Twiddling Hacks page。事實上,你可以找到一個很簡單的算法,你想要做什麼......

反位的明顯的方式

unsigned int v;  // input bits to be reversed 
unsigned int r = v; // r will be reversed bits of v; first get LSB of v 
int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end 

for (v >>= 1; v; v >>= 1) 
{ 
    r <<= 1; 
    r |= v & 1; 
    s--; 
} 
r <<= s; // shift when v's highest bits are zero 

2004年10月15日,邁克爾·Hoisie中指出的錯誤原始版本。 Randal E. Bryant建議在2005年5月3日刪除額外的操作。Behdad Esfabod提出了一個稍微的改變,在2005年5月18日消除了該循環的一次迭代。然後,2007年2月6日,Liyong Zhou提出了一個更好的版本,而v不是0,所以不要遍歷所有位,而是儘早停止。

但是,也有一些漂亮的方法記錄在那裏。你可以看看這些,並嘗試瞭解他們的學習:-)例如,這裏是一個特別有趣的形式...

反向5 * LG電子(N)操作並行的N位數量:

unsigned int v; // 32-bit word to reverse bit order 

// swap odd and even bits 
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); 
// swap consecutive pairs 
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); 
// swap nibbles ... 
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); 
// swap bytes 
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); 
// swap 2-byte long pairs 
v = (v >> 16   ) | (v    << 16); 

注意,如果sizeof(unsigned short) * CHAR_BIT16,適當的使用將只需要前4個換位 - 見如下:

unsigned short v; 

// swap odd and even bits 
v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1); 
// swap consecutive pairs 
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2); 
// swap nibbles ... 
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4); 
// swap bytes 
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8); 

這就是說,爲什麼不只是使用uint16_t(如果它是可用的)?

這裏是工作的例子(見ideone):

#include <stdio.h> 
#include <assert.h> 
#include <stdint.h> 

inline uint16_t reverse(uint16_t v) { 
    v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1); /* swap odd/even bits */ 
    v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2); /* swap bit pairs */ 
    v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4); /* swap nibbles */ 
    v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8); /* swap bytes */ 
    return v; 
} 

main() { 
    uint16_t gf_t = 44; 
    printf("%hu\n", reverse(gf_t)); 
} 
1

通常你用and輸入1來得到它的LSB。 Or即成結果。將結果左移一點,右輸入一點。重複總共32次迭代。

4

你可以像下面這樣做(v是一個16位數字):

v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1); 
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2); 
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4); 
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8); 
  • 第一行是交換奇數和偶數位
  • 第二行互換對
  • 第三行交換的四位
  • 組的最後一行交換兩個字節

你可以找到更多的花樣這樣here。這是一個link to ideone with this code snippet

如果你想使這個意義上說,寫在本例中使用的 「幻數」 的二進制表示:

  • 0x55550101010101010101
  • 0x33330011001100110011
  • 0x0F0F0000111100001111
  • 0x00FF0000000011111111

&操作清除「不需要的」位;這些移位將所需部分重新定位在由掩蔽操作打開的「零間隙」上,最後|重新組合這兩個部分。

0

二進制文件是0000000000101100 - 短中有16位。

//包括去這裏

int main() { 

無符號短gf_t = 44; cout < <十六進制< < gf_t < < endl;

unsigned short gf_r = 0; 
for (int iter = 0; iter < sizeof(short) * 8; ++iter) 
{ 
unsigned short tmp = gf_t; 
tmp = tmp & 1; 
gf_r = (gf_r << 1) | tmp; 
gf_t = gf_t >> 1; 
} 

cout << hex << gf_r << endl; 

}