【问题标题】:Bit manipulation of integers depending on endianess根据字节顺序对整数进行位操作
【发布时间】:2012-07-10 18:14:06
【问题描述】:

我的问题涉及字节序变化时的位操作。特别是我有一些代码可以读取uint32_t 值的各个位并对其执行位操作。目的是 UTF-8 编码。它非常适合我的小端机器。

最近重温代码让我恍然大悟,就uint32_t 值的位表示而言,我并没有考虑机器的字节顺序。所以我对这方面有一些疑问。

让我们假设一个示例代码只需要将 uint32_t 的第 7-10 位保存在不同的字节中。

uint32_t v;
v = 18341;
char c = (v &(uint32_t) 0x3C0)>>6;

对于 little endian,数字 18341 表示为 0x47A5 或二进制:

0100 0111 1010 0101

上面的代码应该给我们 1110 存储在 char 中

现在的问题是我们如何在 Big Endian 机器中实现这一点? 0xA5470000 或二进制表示相同的数字会完全不同:

1010 0101 0100 0111 0000 0000 0000 0000

我们寻求的位处于完全不同的位置,甚至没有结果。

除了在 & 的另一边使用0x3C0,我们将不得不使用其他东西 因为字节顺序不同。特别是因为我们需要一个字节的后续位,我们需要多个布尔 & 操作,如下右图?

char c = ((v&(uint32_t)0xc0)>>6) | ((v&(uint32_t)0x300)>>6)

总结。我的理解是否正确,在我们需要获取以二进制表示的整数值的连续位的情况下,我们需要对两种字节序情况执行不同的操作?

最后有没有比我上面展示的更好的方法来实现相同的目标?也许我遗漏了一些非常明显的东西。

【问题讨论】:

  • 字节序仅在重新解释一段记忆时才相关。

标签: c bit-manipulation endianness


【解决方案1】:

没有。如果您使用值(如 0x300)和语言运算符(

如果你是直接处理内存表示,你可以在操作之前转换表示:

#if defined (BENDIAN)
   val = makelittle(val);
#endif
   manip_lendian(val);
#if defined (BENDIAN)
   val = makebig(val);
#endif

还有see this answer

【讨论】:

  • 是的,我当然可以,也许这是克服头疼的好方法,但是如果我真的尝试使用 big endian 作为不同的函数进行操作,如上所示?这是它应该如何工作的吗?基本上我的问题是这样的,因为我目前没有可用的大端机器,也无法测试我上面写的代码。
  • 嗯,我有点困惑。 0x300 作为一个值在不同的字节序机器中表示不同,对吧?而 >> 或
  • 是的,您的结果不会有任何差异。您不必担心这些操作的表示。
  • 嗯,您的链接答案似乎表明确实没有区别。如果我理解正确,答案表明没有必要像我在问题中的 Big Endian 案例中发布的那样做任何事情,因为语言本身可以确保它们保持一致。这让我头疼不已。
  • Endian 仅在从内存中存储或加载值时才重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多