【发布时间】:2021-10-15 05:55:06
【问题描述】:
我的结构如下所示:
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,因为联合填充到 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)。
【问题讨论】:
-
简短回答,否。该标准不允许控制对象的填充方式。
-
8+12=20。你从哪里得到 16 个?
-
@VictorEijkhout 这是一个工会。它的大小将是最大成员的大小,加上可能的填充。
-
欢迎来到C++的大伞。在许多平台上忽略对齐包装会使结构无法使用,而且它无法使用,这有什么意义呢?
-
您可以将 A 更改为
std::byte A[sizeof(uint8_t*)];,然后将memcpy指针移入 A 并移出 A。