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
。)
强制三元组具有不同偏移量的最佳方法是什么?
我可以在中间粘贴一些人造的 double
s 来匹配偏移量:
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-members , https://web.archive.org/web/20190101225513/http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649。
似乎在中间添加数组至少在当时是一种解决方案。此外,我可以使用 char[N]
进行更精细的控制,以这种方式达到字节级别。
在结构中间添加数组是为结构成员创建正确填充的传统方法,没有问题。我有一个关于使用 ((packed))
和 ((aligned))
的 ,以防你想按你喜欢的方式对齐你的结构。
我可能是错的,但我认为你想要实现的是某种未定义的行为,原因有两个。如果你想按照你描述的方式访问数组中的结构成员:
- 您在数组的不同不相关数据成员之间创建关系。
- 您不能再直接使用数组的属性。例如,你如何理解你是数组的最后一个成员?你需要比较成员的地址和数组的结束地址。
不过,如果你把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))
属性。刚收到此警告,我自己正在尝试对其进行测试。
在结构内对齐成员的最佳或常规方法是什么? 添加虚拟数组是最好的解决方案吗?
我有一个 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
。)
强制三元组具有不同偏移量的最佳方法是什么?
我可以在中间粘贴一些人造的 double
s 来匹配偏移量:
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-members , https://web.archive.org/web/20190101225513/http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649。
似乎在中间添加数组至少在当时是一种解决方案。此外,我可以使用 char[N]
进行更精细的控制,以这种方式达到字节级别。
在结构中间添加数组是为结构成员创建正确填充的传统方法,没有问题。我有一个关于使用 ((packed))
和 ((aligned))
的
我可能是错的,但我认为你想要实现的是某种未定义的行为,原因有两个。如果你想按照你描述的方式访问数组中的结构成员:
- 您在数组的不同不相关数据成员之间创建关系。
- 您不能再直接使用数组的属性。例如,你如何理解你是数组的最后一个成员?你需要比较成员的地址和数组的结束地址。
不过,如果你把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))
属性。刚收到此警告,我自己正在尝试对其进行测试。