【问题标题】:Endianness within uint12 structuint12 结构中的字节序
【发布时间】:2014-03-05 05:44:10
【问题描述】:

假设我有数据,如下所示:

union
{
  struct
  {
    char flags : 4;
    uint16_t   : 12;
  }
  char data[2];
}

我了解如何使此代码在平台上不受字节字节序的影响而运行。我要求确保我对如何将其存储在不同字节序上的理解是正确的。

据我了解: 如果我将 uint16 存储在 12 位 uint 中,则两个字节序都会丢弃 4 个最高位。 Big-endian 会将剩余的 4 个高位存储在与标志相同的字节中,其余的存储在单独的字节中。 Little-endian 会将最低 4 位存储在与标志相同的字节中,其余的则存储在单独的字节中。

这样对吗?

【问题讨论】:

  • C++ 规范试图定义和提供一种逻辑正确的语言,而不是一种对bit正确的语言;如果这对你有某种意义。换句话说,C++ 不关心也不指定在位级别使用的信息的表示,这与您无法将float 推断为模板参数的原因类似,C++没有为float 的表示提供定义,因此它甚至不能提供一些对模板必不可少的基本保证。这一切都是编译器和 ABI 特定的。

标签: c++ struct endianness unions


【解决方案1】:

这取决于编译器和目标平台的 ABI。见,例如GCC bit-fields 的规则:一个单元内位域的分配顺序由 ABI 决定的。此外,每个字段都应该声明为 intunsigned int,而不是 uint16_t

如果要控制数据格式,可以使用移位和屏蔽将数据组装成uint16_t。如果您的目标是以明确定义的格式写出数据,您可以按所需的字节序写入 uint16_t 字节,或者将数据组装成 2 个字节并按所需的顺序写入。

除非您找到了可以满足您需求的语言规范文档,或者您的编译器文档做出了明确的承诺,并且您对大小端 CPU 使用相同的编译器,否则不要依赖 C/C++ 编译器来完成任何事情同样的方式。

【讨论】:

  • 那么它不仅取决于平台,还取决于您使用的编译器?现在想起来,我记得uint16_t 没有定义为基本类型,它是在单独的标头中声明的。位域应该只支持基本类型是有道理的。我最初的希望是我可以在每条消息中包含一个“字节顺序”字段,如果主机与消息的发送者具有相同的字节顺序,那么我可以跳过位移并将原始数据加载到上面的联合中。我发现这行不通。
  • 字段之间的填充也可能因编译器和目标平台而异。通常的方法是始终以“网络字节顺序”(即大端)发送数据。有关示例标准,请参阅 XDR。有图书馆可以帮助做到这一点。
  • 感谢您的所有帮助。我了解如何使这种字节序不可知,我只是出于个人兴趣寻找tiny 优化。我无法编写依赖于如此挑剔的代码的代码。显然,对于字节大小的数据,填充几乎总是不存在的。支持您的答案,因为您非常乐于助人。
  • 很高兴为您提供帮助,@Andrew
猜你喜欢
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多