将内存转换为联合

时间:2016-11-23 19:54:02

标签: c++ casting bit-fields memory-layout

我想分配一些内存,将其初始化为某些值,然后将此内存的不同段转换为不同的结构。如下:

union structA{
  __int8 mem[3];

  struct{
    unsigned field1 : 8;
    unsigned field2 : 12; 
    unsigned field3 : 4;
  };
};

struct structB{
  __int8 mem[10];
};


__int8 globalMem[128];

structA a1 <---- &globalMem[0]
structA a2 <---- &globalMem[10]
structB b1 <---- &globalMem[30]

我尝试使用reinterpret_cast并且我没有收到任何编译器错误,但似乎我的变量(a1a2b1)并未真正正确分配/初始化

任何想法为什么这不起作用以及实现这样的事情的正确方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

要实现您的目标,需要使用reinterpret_cast

structA a1 = *reinterpret_cast<structA*>(&globalMem[0]);
structA a2 = *reinterpret_cast<structA*>(&globalMem[10]);
structB b1 = *reinterpret_cast<structB*>(&globalMem[30]);

这有什么问题?

这需要特别小心,因为C ++ struct是一种特殊的class,这种赋值不尊重对象语义(因为不同globalMem的内容除非您在代码中的某处使用placement new,否则地址不会初始化为正确的对象。

在使用此类技巧之前,您还可以确保structA可以轻松复制(is_trivially_copyable<structA>::value,幸运的是这里是真的)。

此外,由于globalMem没有对齐约束,因此可能存在可能无法遵守的对齐约束的问题,但是根据编译器/体系结构,structA可能需要字对齐。

最后,structA的大小不一定是3,因为你倾向于思考。实际上在一些编译器上它将是4,如 this online demo

补充说明

您可以使用标准类型uint8_t而不是以双下划线开头的编译器特定类型名称。

关于对齐和大小主题,我建议您对内存布局假设非常谨慎。我建议您globalMem考虑将其作为所包含的所有结构的结构,以确保正确的对象语义并具有安全的布局。