我的问题涉及结束性变化时的位操作。特别是我有一些代码读取uint32_t
值的各个位并对它们执行位操作。目的是UTF-8编码。它适用于我的小端机。
最近重新审视了代码我突然意识到,就uint32_t
值的位表示而言,我并没有考虑机器的endianess。所以我对这方面有一些疑问。
我们假设一个示例代码只需要保存在不同字节中的uint32_t
的第7-10位。
uint32_t v;
v = 18341;
char c = (v &(uint32_t) 0x3C0)>>6;
对于小端,数字18341表示为0x47A5
或二进制:
0100 01 11 10 10 0101
以上代码应该给我们存储在char
中的1110现在问题是我们将如何在Big Endian机器中实现这一目标?相同的数字将以完全不同的方式表示0xA5470000
或二进制:
10 10 0101 0100 01 11 0000 0000 0000 0000
我们寻求的位置处于完全不同的位置,甚至没有结果。
我们不得不在& 的另一边使用0x3C0
,而是使用别的东西
因为字节顺序不同。特别是因为我们需要一个字节的后续位,我们需要多个布尔& 操作,如下所示?
char c = ((v&(uint32_t)0xc0)>>6) | ((v&(uint32_t)0x300)>>6)
总结。我的理解是正确的,在我们需要获得以二进制表示的整数值的连续位的情况下,我们需要对两个endianess情况执行不同的操作吗?
最后是否有更好的方法来实现与上面展示的相同的东西?也许我错过了一些非常明显的东西。
答案 0 :(得分:1)
没有。如果您使用的值(如0x300)和语言运算符(<<,|,&)则无关紧要,因为该值将根据机器表示。因此,在您的情况下,您不必担心这个问题。例如,当您将文件中的字节复制到内存中时,您应该担心。
如果直接处理内存表示,可以在操作之前转换表示:
#if defined (BENDIAN)
val = makelittle(val);
#endif
manip_lendian(val);
#if defined (BENDIAN)
val = makebig(val);
#endif