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

piy*_*iya 5 c++ bit-manipulation bit-shift

#define SwapByte4(ldata) \
   (((ldata & 0x000000FF) << 24) | \
   ((ldata & 0x0000FF00) << 8) | \
   ((ldata & 0x00FF0000) >> 8) | \
   ((ldata & 0xFF000000) >> 24))
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*ery 32

这是一个十六进制值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位字节的序列,并反转它们的顺序.


小智 5

这种代码往往用于在big endian和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);
Run Code Online (Sandbox Code Playgroud)

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

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