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

0x000000FF 代表什么?我知道十进制 15 用十六进制表示为 F,但为什么它是 << 24?

4

4 回答 4

38

这是一个十六进制值,0x12345678,写成二进制,并用一些位位置进行了注释:

|31 24|23 16|15 8|7 位 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|
+---------------+---------------+---------------+- --------------+

所以按位 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(如上图)

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

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

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

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

所以整体效果就是把 32 位的值ldata看成是 4 个 8 位字节的序列,并把它们的顺序颠倒过来。

于 2010-10-30T12:19:12.120 回答
5

这种代码往往被用来在大端和小端格式之间交换东西。还有一个小技巧可以将某个已知格式的单词(比如说,小端)转换为当前机器恰好是的任何字节序,反之亦然。那会是这样的:

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,否则它只会溢出您的鞋子。此外,+= 不是唯一的选择,|= 可能更有意义,但如果你不习惯,我不确定)

于 2010-10-30T12:52:27.667 回答
2

您需要将0x000000FF视为位掩码,即在哪里ldata取 1 的值,在哪里取 0 - 0。

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

十六进制 0 = 二进制 0000 十六进制 1 = 二进制 0001,依此类推。

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

现在请注意,|在所有位掩码 AND 操作上都有 ie OR 操作,即零将保持为零,如果有“1”,结果将包含一。

希望能帮助到你 :)

于 2010-10-30T10:59:10.260 回答
0

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

Data & 0x000000FF 表示只保留最后 8 位(称为位掩码)= 0x00000078

<< 24 表示将此值向左移动 24 位(78 从位置 24 [0 索引] 开始)= 0x78000000

该| 表示合乎逻辑或在这种情况下只是一个加法

最终结果 = 0x78563412

阅读逻辑操作

于 2010-10-30T12:23:29.603 回答