#define SwapByte4(ldata) \
(((ldata & 0x000000FF) << 24) | \
((ldata & 0x0000FF00) << 8) | \
((ldata & 0x00FF0000) >> 8) | \
((ldata & 0xFF000000) >> 24))
0x000000FF 代表什么?我知道十进制 15 用十六进制表示为 F,但为什么它是 << 24?
#define SwapByte4(ldata) \
(((ldata & 0x000000FF) << 24) | \
((ldata & 0x0000FF00) << 8) | \
((ldata & 0x00FF0000) >> 8) | \
((ldata & 0xFF000000) >> 24))
0x000000FF 代表什么?我知道十进制 15 用十六进制表示为 F,但为什么它是 << 24?
这是一个十六进制值,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 位字节的序列,并把它们的顺序颠倒过来。
这种代码往往被用来在大端和小端格式之间交换东西。还有一个小技巧可以将某个已知格式的单词(比如说,小端)转换为当前机器恰好是的任何字节序,反之亦然。那会是这样的:
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,否则它只会溢出您的鞋子。此外,+= 不是唯一的选择,|= 可能更有意义,但如果你不习惯,我不确定)
您需要将0x000000FF
视为位掩码,即在哪里ldata
取 1 的值,在哪里取 0 - 0。
为了理解位掩码,您需要将其转换为二进制,使用十六进制非常容易,每个十六进制数都是 4 个二进制数字,即:
十六进制 0 = 二进制 0000 十六进制 1 = 二进制 0001,依此类推。
现在开始移位:请注意,移位从源中获取一些数据,精确到 8 位,并将其移动到目标中的另一个位置。
现在请注意,|
在所有位掩码 AND 操作上都有 ie OR 操作,即零将保持为零,如果有“1”,结果将包含一。
希望能帮助到你 :)
假设数据是一个 32 位数字,表示为 0x12345678(每个数字是 4 位十六进制)
Data & 0x000000FF 表示只保留最后 8 位(称为位掩码)= 0x00000078
<< 24 表示将此值向左移动 24 位(78 从位置 24 [0 索引] 开始)= 0x78000000
该| 表示合乎逻辑或在这种情况下只是一个加法
最终结果 = 0x78563412
阅读逻辑操作