首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >把记忆铸造成联盟

把记忆铸造成联盟
EN

Stack Overflow用户
提问于 2016-11-23 19:54:02
回答 1查看 84关注 0票数 2

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

代码语言:javascript
复制
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)似乎没有被正确地分配/初始化。

你知不知道为什么这样做不起作用,实现这种目标的正确方法是什么?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-23 20:07:47

要实现您想要做的事情,需要使用reinterpret_cast

代码语言:javascript
复制
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地址的内容不会初始化为适当的对象,除非您在代码中的某个地方使用安置新 )。

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

此外,由于globalMem没有对齐约束,因此可能存在对齐约束的问题,但根据编译器/体系结构的不同,structA可能需要单词对齐。

最后,structA的大小不一定如您所想的那样是3。事实上,在某些编译器上,它将是4,就像在这个在线演示中一样

附加备注

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40773080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档