铸造记忆联合
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,但我没有收到任何编译器错误,但似乎我的变量(a1
、a2
和 b1
)并不是真的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
考虑使它成为它包含的所有结构的结构,以确保正确的对象语义和安全的布局。
我想分配一些内存,将其初始化为一些值,然后将此内存的不同段转换为不同的结构。内容如下:
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,但我没有收到任何编译器错误,但似乎我的变量(a1
、a2
和 b1
)并不是真的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
考虑使它成为它包含的所有结构的结构,以确保正确的对象语义和安全的布局。