Align/offset specific members of a struct

梦想的初衷 提交于 2020-06-13 05:47:10

问题


What is the best or conventional method to align members inside a structure? Is adding dummy arrays the best solution?

I have a struct of double and a triple of doubles?

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

If I have an array of these, the memory will look like this

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

The problem is that the distance from the first triple to the second triple is not an integer multiple of sizeof(std::tuple<double, double,double>)==3*sizeof(double), therefore I cannot interpret the interleaved array of triples as an array with strides.

In other words, given an array of particles particle ps[100], I can to take the address of a member to the first element triple* v1P = &(ps[0].position) and I want that v1P + n == &(ps[1].position) for some (integer) n (that I can deduce at compile-time, for example n = sizeof(particle)/sizeof(tripe) if sizeof(particle)%sizeof(tripe)==0.)

What is the best method to force the triple to have a different offset?

I could stick a number of artificial doubles in the middle to match the offset:

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

So memory will look like this

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

but then I cannot use initializers (particle{1.,{1.,2.,3.}}).

I could also add it to the end

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

So, I can keep using the initializer. Is this the best method? But it will only work in this simple case.

Another alternative could be to force alignment of the struct to some multiple of the 3*sizeof(double)

struct alignas(3*sizeof(double)) particle{double mass; std::tuple<...> position;};

but the problem is that it is not a power of 2, so GCC and clang reject it. Note that in other sizes of the tuple the alignas strategy works because it can solve the problem being accidentally a power of two.

For example in

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

alignas gives an easy solution for this other use case (in GCC).

Is there a general or accepted solution for this?

I also found about ((packed)), is that also necessary in this solution?


I found this old article 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 . It seems that adding arrays in the middle of was a solution back then at least. Moreover, I could use char[N] to have finer control, to the level of a byte in this way.


回答1:


Adding arrays in middle of structures is a traditional way to create correct padding for members of structure and there is no problem with it. I have a thread on using ((packed)) and ((aligned)) in case you want to align your structure as you like.

I may be wrong, but I think what you want to achieve is somehow undefined behavior for 2 reasons. If you want to access members of structure in array in the way you describe:

  1. You create relationship between different unrelated data members of array.
  2. You cannot use properties of array directly anymore. e.g how you understand you are at the last member of array? You need to compare address of members with ending address of array.

Though, if you set structure padding to 1 (with ((packed))) should guarantee what you want to do, but I personally don't suggest it.

Update following structure:

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

gives you similar strides as:

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

But since tuple<> is a non-POD, you cannot use ((packed)) attribute. Just got this warning myself trying to test it.



来源:https://stackoverflow.com/questions/57424150/align-offset-specific-members-of-a-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!