我有一个看起来像这样的结构:
struct vdata {
static_assert(sizeof(uint8_t *) == 8L, "size of pointer must be 8");
union union_data {
uint8_t * A; // 8 bytes
uint8_t B[12]; // 12 bytes
} u;
int16_t C; // 2 bytes
int16_t D; // 2 bytes
};
我想把它设为 16 字节,但 GCC 告诉我它是 24,因为 union 正在填充到 16 字节。
我想将 vdata 放入一个大的 std::vector
中。根据我的理解,如果这是 16 个字节,则对齐应该没有问题,因为指针始终是 8 个字节对齐的。
我知道我可以在 GCC 中使用 __attribute__((__packed__))
强制打包它。但我想知道是否有一种可移植且符合标准的方法可以将其设置为 16 字节?
编辑:想法
思路一:拆分B数组。
struct vdata {
union union_data {
uint8_t * A; // 8 bytes
uint8_t B[8]; // 8 bytes
} u;
uint8_t B2[4]; // 4 bytes
int16_t C; // 2 bytes
int16_t D; // 2 bytes
};
可以从 B 的指针可靠地访问 B2 元素吗?这是定义的行为吗?
想法 2:将指针存储为字节数组并根据需要存储 memcpy (@Eljay)
struct vdata {
union union_data {
std::byte A[sizeof(uint8_t*)]; // 8 bytes
uint8_t B[12]; // 12 bytes
} u;
int16_t C; // 2 bytes
int16_t D; // 2 bytes
};
访问指针会导致性能下降,还是会被优化掉? (假设 GCC x86)。
最佳答案
您可以将 A
更改为 std::byte A[sizeof(uint8_t*)];
然后将 std::memcpy
指针进入 A
并离开 A
。
关于正在发生的事情值得评论,这些额外的环是为了避免填充字节。
同时添加一个 set_A
setter 和 get_A
getter 可能会很有帮助。
struct vdata {
union union_data {
std::byte A[sizeof(uint8_t*)]; // 8 bytes
uint8_t B[12]; // 12 bytes
} u;
int16_t C; // 2 bytes
int16_t D; // 2 bytes
void set_A(uint8_t* p) {
std::memcpy(u.A, &p, sizeof p);
}
uint8_t* get_A() {
uint8_t* result;
std::memcpy(&result, u.A, sizeof result);
return result;
}
};
关于c++ - 打包 union/结构以避免填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68747627/