Align/offset 结构的特定成员

Align/offset specific members of a struct

在结构内对齐成员的最佳或常规方法是什么? 添加虚拟数组是最好的解决方案吗?

我有一个 double 的结构和一个 double 的三元组?

struct particle{
  double mass;
  std::tuple<double, double, double> position;
}

如果我有这些的数组,内存将如下所示

[d][d  d  d][d][d  d  d][d][d  d  d]...

问题是从第一个三元组到第二个三元组的距离不是 sizeof(std::tuple<double, double,double>)==3*sizeof(double) 的整数倍,因此我无法将交错的三元组数组解释为具有 步幅的数组.

换句话说,给定一个粒子数组 particle ps[100],我可以将成员的地址取到第一个元素 triple* v1P = &(ps[0].position),我希望 v1P + n == &(ps[1].position) 用于 some(整数)n(我可以在编译时推断,例如 n = sizeof(particle)/sizeof(tripe) if sizeof(particle)%sizeof(tripe)==0。)

强制三元组具有不同偏移量的最佳方法是什么?

我可以在中间粘贴一些人造的 doubles 来匹配偏移量:

struct particle{
  double mass;
  double garbage[2];
  std::tuple<double, double, double> position;
}

所以内存看起来像这样

[d][*  *][d  d  d][d][*  *][d  d  d][d][*  *][d  d  d]...

但是我不能使用初始值设定项 (particle{1.,{1.,2.,3.}})。

我也可以把它加到最后

struct particle{
  double mass;
  std::tuple<double, double, double> position;
  double garbage[2];
}

所以,我可以继续使用初始化程序。这是最好的方法吗?但它只适用于这种简单的情况。

另一种选择是强制 struct3*sizeof(double)

的某个倍数对齐
struct alignas(3*sizeof(double)) particle{double mass; std::tuple<...> position;};

但问题是它不是 2 的幂,所以 GCC 和 clang 拒绝它。请注意,在其他大小的元组中,alignas 策略有效,因为它可以解决 意外地 2 的幂的问题。

例如在

struct alignas(4*sizeof(double)) particle{double mass; std::pair<double, double> position;};

alignas 为这个其他用例(在 GCC 中)提供了一个简单的解决方案。

是否有通用或公认的解决方案?

我也找到了关于 ((packed)),这个解决方案是否也有必要?


我找到了这篇旧文章 https://www.embedded.com/design/prototyping-and-development/4008281/2/Padding-and-rearranging-structure-members , https://web.archive.org/web/20190101225513/http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649。 似乎在中间添加数组至少在当时是一种解决方案。此外,我可以使用 char[N] 进行更精细的控制,以这种方式达到字节级别。

在结构中间添加数组是为结构成员创建正确填充的传统方法,没有问题。我有一个关于使用 ((packed))((aligned)),以防你想按你喜欢的方式对齐你的结构。

我可能是错的,但我认为你想要实现的是某种未定义的行为,原因有两个。如果你想按照你描述的方式访问数组中的结构成员:

  1. 您在数组的不同不相关数据成员之间创建关系。
  2. 您不能再直接使用数组的属性。例如,你如何理解你是数组的最后一个成员?你需要比较成员的地址和数组的结束地址。

不过,如果你把structure padding设置为1(with ((packed)))应该可以保证你想做什么,但我个人不建议这样做。

更新 以下结构:

struct particle{
  double mass;
  __attribute__((aligned(2*sizeof(double)))) std::tuple<double, double, double> position;
};

给你类似的步伐:

struct particle{
  double mass;
  double garbage[2];
  std::tuple<double, double, double> position;
}

但由于 tuple<> 是非 POD,您不能使用 ((packed)) 属性。刚收到此警告,我自己正在尝试对其进行测试。