1

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

我有一个结构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),因此我不能将交错的三元组数组解释为 strides 的数组

换句话说,给定一个粒子数组particle ps[100],我可以将成员的地址带到第一个元素triple* v1P = &(ps[0].position),并且我想要一些v1P + n == &(ps[1].position)(整数)(我可以在编译时推断,例如if 。)nn = sizeof(particle)/sizeof(tripe)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];
}

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

另一种选择可能是强制对齐struct到某个倍数3*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-membershttps://web.archive.org/web/20190101225513 /http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649。至少在当时,在中间添加数组似乎是一种解决方案。此外,我可以使用char[N]这种方式进行更精细的控制,达到一个字节的级别。

4

1 回答 1

1

在结构中间添加数组是为结构成员创建正确填充的传统方法,并且没有问题。我有一个关于使用的线程((packed))((aligned))以防你想根据需要调整结构。

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

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

虽然,如果您将结构填充设置为 1(使用((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))属性。刚收到这个警告我自己试图测试它。

于 2019-08-09T06:47:30.223 回答