/ Swap endian (big to little) or (little to big)
uint32_t num = 9;
uint32_t b0,b1,b2,b3;
uint32_t res;
b0 = (num & 0x000000ff) << 24u;
b1 = (num & 0x0000ff00) << 8u;
b2 = (num & 0x00ff0000) >> 8u;
b3 = (num & 0xff000000) >> 24u;
res = b0 | b1 | b2 | b3;
我从Convert Little Endian to Big Endian
发布的答案中获得了此代码我理解上面的步骤将字节交换为从小端转换为大端。为什么“&amp;”用(0x0000FF00,....)表示每一步的b0,b1,..和“|”到底为了结果呢?有人可以解释这些可以帮助我理解endianess之间转换的疑问。
答案 0 :(得分:6)
这样你就可以屏蔽掉比特并设置比特。至少这是简单的答案。在C,&amp;是按位AND运算符和|是按位OR运算符(与用于布尔运算的逻辑&amp;&amp;和||略有不同)。看看下面的真相表。
AND OR
A B X A B X
0 0 0 0 0 0
0 1 0 0 1 1
1 0 0 1 0 1
1 1 1 1 1 1
A和B是输入,X是输出。所以当你进行16位字节序交换时,你会使用这样的宏:
#define endianswap16(x) (x << 8) | (x >> 8)
这需要x,进行移位,然后将结果进行OR运算以获得endian交换。采用32位端接交换,使用&amp;和|除了位移:
#define endianswap32(x) (x << 24) | (x & 0x0000FF00) << 8) \
| (x & 0x00FF0000) >> 8) | (x >> 24)
由于32位是4个字节,因此将两个外部字节相互交换,然后将两个内部字节相互交换。然后它执行逻辑OR以将32位数字重新组合在一起。 AND用于掩盖certian位的位置,因此当我们执行OR来重建数字时,我们不会更改该值。
关于我们为什么这样做的问题,这是因为我们必须颠倒字节的顺序。以0x12345678为例。当存储在小型和大型端机器上的内存中时,它看起来像这样:
---> Increasing Memory Address
78 56 34 12 Little Endian
12 34 56 78 Big Endian
英特尔和他们的克隆是小端机器,实际上比大端格式有优势。 Big endian机器是IBN S / 360和后代(Z-architecture),Sparc,Motorola 68000系列和PowerPC,MIPS等。
在处理不同的平台时,有两个大问题:
这方面的一个例子是英特尔机器通过网络进行通信。网络地址是网络字节顺序,这是大端,但英特尔机器是小端。因此,IP地址和其他人需要交换它们才能正确解释它们。
答案 1 :(得分:1)
相当简单的位屏蔽和移位。
(num & 0x000000ff)
除了单词的一个字节外都是零。 << 24u
将它移位24位或3位8位字节,将其置于单词的另一端。接下来的三行以类似的方式交换剩余的3个字节。
然后b1|b2|...
将这些字节组合在一起以形成最终的单词。
请参阅How do you set, clear, and toggle a single bit?和What are bitwise shift (bit-shift) operators and how do they work?。处理单个位的相同操作对位组起作用,在这种情况下是产生一个字节的8位。