2015-02-12 53 views
1

我一直在寻找这个功能在网上,我想知道它是如何工作的:这个reverseBytes方法是如何工作的?

/* 
    * reverseBytes - reverse bytes 
    * Example: reverseBytes(0x12345678) = 0x78563412 
    * Legal ops: ! ~ &^| + << >> 
    */ 
    int reverseBytes(int x) 
    { 
     int newbyte0 = (x >> 24) & 0xff; 
     int newbyte1 = (x >> 8) & 0xff00; 
     int newbyte2 = (x << 8) & 0xff0000; 
     int newbyte3 = x << 24; 

     return newbyte0 | newbyte1 | newbyte2 | newbyte3; 
    } 

这里就是我想我明白:

  • 0xff0xff000xff0000二进制是1111 11111111 1111 0000 0000,和1111 1111 0000 0000 0000 0000分别为
  • 该方法用掩码创建四个新字节(0xff等),然后使用将它们的值相加在一起运营商

我真的不明白这是如何颠倒字节虽然。我希望有详细的解释。谢谢!

回答

2

该代码假定32位整数和8位字节。一个32位整数由4个字节: 比方说,这4个字节的内存布局,像这样:

+---------------------------------+ 
|Byte 4 | Byte 3 | Byte 2 | Byte 1| 
+---------------------------------+ 

这可能与给定的CPU类型的Endianess。当解释一个由几个字节组成的整数时,一些CPU系列将把最左边的字节看作是整数的最重要的字节 - 这种CPU被称为big endian。其他的CPU会做相反的事情,他们会把整数中最右边的字节,最大内存地址的字节当作最重要的字节 - 小端CPU。所以你的函数将一个整数从一个endian转换为另一个endian。

int newbyte0 = (x >> 24) & 0xff; 

这需要上面描述的整数(4个字节),它转移24位到右侧,和掩码关的一切,但低8位,newbyte0看起来现在这个样子,其中,字节4是原始字节4的x和其他3个字节的所有位都设置为零。

+---------------------------------+ 
| 0 | 0 | 0 | Byte 4 | 
+---------------------------------+ 

Similarely

int newbyte1 = (x >> 8) & 0xff00; 

班次位8位到右侧,和面具掉一切,但在从左边的2字节的8位。结果看起来是这个样子,只有3字节剩余原值的x

+---------------------------------+ 
| 0 | 0 | Byte 3 | 0 | 
+---------------------------------+ 

的2最左边的字节被同样处理,只是x左移来完成同样的事情。

最后你

newbyte0 | newbyte1 | newbyte2 | newbyte3; 

,结合上面创建的所有整数,每个从原来的x剩下的只有8位。做一个按位or他们,你最终与

+---------------------------------+ 
|Byte 1 | Byte 2 | Byte 3 | Byte 4| 
+---------------------------------+ 
0

让我们假设你的32位系统已经通过0x12345678这个函数。

int newbyte0 = (x >> 24) & 0xff;  //will be 0x00000012 
int newbyte1 = (x >> 8) & 0xff00; //will be 0x00003400 
int newbyte2 = (x << 8) & 0xff0000; //will be 0x00560000 
int newbyte3 = x << 24;    //will be 0x78000000 

return newbyte0 | newbyte1 | newbyte2 | newbyte3; will be 0x78563412 
0

该函数只是将字节移位到一个整数中的正确位置,而不是将它们全部放在一起。 例如x是0xAABBCCDD: 对于第一个字节,我们将所有字节向右移位,所以我们有0x00000000AA & 0xFF这是0xAA。

对于第二个字节我们有0x00AABBCC &为0xFF00这是0x0000BB00

等。 我们只是将位移到正确的位置并擦除所有其他位。

0

是的,你正确理解代码,但当然它假定int为32位值。

int newbyte0 = (x >> 24) & 0xff; // Shift the bits 24~31 to 0~7 
    int newbyte1 = (x >> 8) & 0xff00; // Shift the bits 16~23 to 8~15 
    int newbyte2 = (x << 8) & 0xff0000; // Shifts bit bits 8~15 to 16~23 
    int newbyte3 = x << 24; // Shift bits 0~7 to 24~31 

    return newbyte0 | newbyte1 | newbyte2 | newbyte3; // Join all the bits 
1
int newbyte0 = (x >> 24) & 0xff; 

档数24位到右侧,让最左边的字节现在将最右边的字节。然后它使用一个掩码(0xff)来清零其余字节,这是多余的,因为移位将它们置零,所以可以省略掩码。

int newbyte1 = (x >> 8) & 0xff00; 

档数8位到右侧,从而使从左侧的第二个字节现在是从右侧的第二个字节,并且字节的其余部分用掩模归零。

int newbyte2 = (x << 8) & 0xff0000; 

档数8位到左边这个时候 - 本质上是一回事的最后一行,现在只有从右边第二个字节变为从左边第二个字节。

int newbyte3 = x << 24; 

同样作为第一线(此时确实省略重复的掩模) - 最右字节成为最左边的字节。

return newbyte0 | newbyte1 | newbyte2 | newbyte3; 

最后你只需要OR所有的字节来完成反转。

实际上,您可以通过使用printf("%x", newbyte)打印每个字节来一步步地在代码中执行此过程 - %x格式允许您以十六进制打印。