【问题标题】:struct/class bit field packing结构/类位域打包
【发布时间】:2016-11-16 22:17:42
【问题描述】:

我想使用 cpp 的位域功能。
但是我得到了各种奇怪的行为,我想知道是否有
一种约束编译器的方法。

我想使用这个位域:

class MyBitField
{
   uint32 a :  8;
   uint32 b : 32;
   uint32 c : 32;
}

现在使用此代码:

uint8 rawData[9] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF, 0xFF};
MyBitField \*pMyBitField = (MyBitField\*)rawData;

我希望(在 little endian 32 位 CPU 上):
pMyBitField 的 a 字段为 0x12,
pMyBitField 的 b 字段为 0x9A785634,
pMyBitField 的 a 字段为 0xFFFFDEBC。

编译器选择进行一些无法解释的对齐。
我知道,如果您在位字段中使用不同的类型,您可能会得到对齐,但事实并非如此。
我该怎么做?

让我们专注于 Visual Studio 2005,但任何其他环境支持也将得到支持。

*我阅读了一些关于包装的帖子,但它并没有改变对齐问题。

谢谢!

【问题讨论】:

  • Google #pragma pack,它是编译器在结构中使用特定对齐的指令......
  • 嗨 Tony,请详细说明 $pragma 的用法
  • 来自 Google 的第一个匹配项,专门与您的编译器相关,包括示例:msdn.microsoft.com/en-us/library/2e70t5y1(v=vs.80).aspx
  • 标准 9.6-1(尽管是旧草案)“类对象中位域的分配是实现定义的。位域的对齐是实现定义的。位域被打包成一些可寻址的分配单元。[注意:位域在某些机器上跨越分配单元,而不在其他机器上。”。所以,它是否有效取决于你的编译器......你说“我读了一些关于打包的帖子,但它并没有改变对齐问题。” - 你尝试了什么,得到了什么结果?

标签: c++ c bit-manipulation


【解决方案1】:

我希望您的代码不会编译。 rawData 有一个数组类型;这个 隐式转换为指针,但不能转换为类 类型,隐式或显式。

剩下的,编译器如何布置位域是实现 已定义,但在您的情况下,我希望它无关紧要;在 32 位 机器,32 位位域通常会强制编译器使用 下一个字,所以只有第一位字段有任何作用。取决于 编译器,它将导致编译器将值置于高位 订购 8 位,或低位 8 位(并保留字的其余部分 未定义)。

如果您需要匹配外部格式,这样做的唯一方法 可靠地是一个字节一个字节地插入任何必要的值 字节。

【讨论】:

  • Visual Studio 确实建议使用 Intel/AMD,其中 CPU 能够进行非对齐寻址(有时会降低性能)。我希望编译器能够满足非性能最佳对齐的打包请求。如果您将可靠与可移植和保证跨编译器版本等一致,则“唯一可靠地执行此操作的方法”可能是正确的,但是如果您准备使用实现定义的行为,它可能会被可靠地定义和实现。 ..
  • 如果打包是唯一的问题,并且您不关心可移植性,您也许可以使用编译指示。在实践中,任何时候打包都是一个问题,所以它是字节顺序,可能还有其他问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多