什么是0xFF,为什么它被移动了24次?

时间:2010-10-30 10:52:02

标签: c++ bit-manipulation bit-shift

#define SwapByte4(ldata) \
   (((ldata & 0x000000FF) << 24) | \
   ((ldata & 0x0000FF00) << 8) | \
   ((ldata & 0x00FF0000) >> 8) | \
   ((ldata & 0xFF000000) >> 24))

0x000000FF代表什么?我知道小数15用十六进制表示为F,但为什么它&lt;&lt; 24?

4 个答案:

答案 0 :(得分:30)

这是一个十六进制值0x12345678,写为二进制,并带有一些位位置注释:

|31           24|23           16|15            8|7         bit 0|
+---------------+---------------+---------------+---------------+
|0 0 0 1 0 0 1 0|0 0 1 1 0 1 0 0|0 1 0 1 0 1 1 0|0 1 1 1 1 0 0 0|
+---------------+---------------+---------------+---------------+

......这里是0x000000FF:

+---------------+---------------+---------------+---------------+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|1 1 1 1 1 1 1 1|
+---------------+---------------+---------------+---------------+

因此,按位AND仅选择原始值的底部8位:

+---------------+---------------+---------------+---------------+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 1 1 1 1 0 0 0|
+---------------+---------------+---------------+---------------+

...并将其向左移动24位将其从底部的8位移到顶部:

+---------------+---------------+---------------+---------------+
|0 1 1 1 1 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|
+---------------+---------------+---------------+---------------+

...十六进制为0x78000000。

其他部分适用于输入的剩余8位部分:

  0x12345678
& 0x000000FF
  ----------
  0x00000078 << 24 = 0x78000000       (as shown above)

  0x12345678
& 0x0000FF00
  ----------
  0x00005600 <<  8 = 0x00560000

  0x12345678
& 0x00FF0000
  ----------
  0x00340000 >>  8 = 0x00003400

  0x12345678
& 0x00000000
  ----------
  0x12000000 >> 24 = 0x00000012

                   | ----------
                     0x78563412

所以整体效果是将32位值ldata视为四个8位字节的序列,并颠倒它们的顺序。

答案 1 :(得分:5)

这种代码往往用于在big endian and little endian格式之间交换内容。还有一个小技巧可以将一些已知格式的单词(比方说,小端)转换为当前机器所遇到的任何字节顺序,反之亦然。这将是这样的:

unsigned long littleEndian;
unsigned char* littleBytes = &littleEndian;
unsigned long result = 0;
for (i = 0; i < 4; i++)
    result += unsigned long(littleBytes[i]) << (8 * i);

这是有效的(假设我没有弄乱它),因为无论实际存储的是多少字节,左移都可以保证向更高位移位。转换为char *允许您按照它们实际存储在内存中的顺序访问字节。使用此技巧,您无需检测机器字节序以读取/写入已知格式的内容。不可否认,你也可以使用标准函数(hton等):P

(注意:你必须要小心一点,然后在转移之前施放char,否则它只会溢出你的鞋子。而且,+ =不是唯一的选择,| =可能会更有意义,但可能是不太清楚,如果你不习惯,我不确定)

答案 2 :(得分:2)

你需要将0x000000FF看作一个位掩码,即它的值为1 ldata将被取代,并且它将取0 - 0。

为了理解你需要将其转换为二进制的位掩码,使用hex非常容易,每个十六进制数字都是4个二进制数字,即:

hex 0 =二进制0000 十六进制1 =二进制0001 等等。

现在转换:请注意,转移从源获取一些数据,准确地取出8位,并将其移动到目标中的另一个位置。

现在请注意,|即对所有位掩码AND操作进行OR运算,即零将保持为零,如果为'1',则结果将包含一个。

希望有所帮助:)

答案 3 :(得分:0)

假设数据是32位数字,表示为0x12345678(每个数字为4位十六进制)

数据&amp; 0x000000FF表示仅保留最后8位(称为位掩码) = 0x00000078

&lt;&lt; 24表示将此值移至左侧24位(位置24处开始78 [0索引]) = 0x78000000

|意味着逻辑或在这种情况下只是一个加法

最终结果= 0x78563412

阅读逻辑操作