铸造记忆联合

Casting memory to union

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

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)并不是真的assigned/initialized正确。

知道为什么这不起作用吗?实现类似目标的正确方法是什么?

谢谢!

要实现您的目标,需要使用 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 addresses 未初始化为正确的对象,除非您在代码中的某处使用 placement new )。

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

此外,可能存在不遵守对齐约束的问题,因为 globalMem 没有对齐约束,但根据 compiler/architecture,structA 可能需要单词对齐。

最后,structA的大小不一定是你想的那样3。事实上,在某些编译器上它将是 4,如 this online demo

补充说明

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

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