c++ - 打包 union/结构以避免填充

标签 c++ padding

我有一个看起来像这样的结构:

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/

相关文章:

c++ - C++接口(interface)的使用方法

c++ - 如何克服 OpenCV 和 RTMaps 中 struct C++ 的双重声明?

c++ - MSVC 默认内存对齐为 8

java - 删除 GridbagLayout 中的空白

html - 帮助缩小表大小

c++ - 找不到全局命名空间范围内的函数名称

c++ - 使用链表确定适当的子集

c++ - 位图文件图像数据偏移产生不同图像

jQuery如何获取元素的边距和填充?

html - 无法向图像添加填充