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

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)没有真正正确地分配/初始化。

关于为什么这样不起作用以及实现这样的东西的正确方法有什么想法?

谢谢!

最佳答案

要实现您打算做的事情,需要使用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,并且这种分配不尊重对象的语义(因为除非将placement new用于以下位置,否则不同globalMem地址处的内容不会初始化为适当的对象。您的代码)。

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

另外,可能存在不遵守对齐约束的问题,因为globalMem没有对齐约束,但是根据编译器/体系结构,structA可能需要单词对齐。

最后,structA的大小不一定像您想的那样为3。实际上,在某些编译器中,它将是4,例如 this online demo

附加说明

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

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

10-07 16:45