如果结构成员的对齐方式已知,是否可以找到结构类型的对齐方式?
例如。为了:
struct S
{
a_t a;
b_t b;
c_t c[];
};
是 S = max(alignment_of(a), alignment_of(b), alignment_of(c)) 的对齐方式吗?
在互联网上搜索我发现“对于结构化类型,其任何元素的最大对齐要求决定了结构的对齐”(在What Every Programmer Should Know About Memory中)但我在标准中找不到任何类似的东西(最新更准确地起草)。
编辑: 非常感谢所有的答案,特别是罗伯特甘布尔,他对原始问题和其他做出贡献的人提供了非常好的答案。
简而言之:
为了确保结构成员的对齐要求,结构的对齐必须至少与其最严格的成员的对齐一样严格。
至于确定结构的对齐方式,提出了一些选择,经过一些研究,我发现:
- c++ std::tr1::alignment_of
- 尚未标准,但接近(技术报告 1),应该在 C++0x 中
- 最新草案中存在以下限制: 前提条件:T 应是完整类型、引用类型或未知边界数组,但不应是函数类型或(可能是 cv 限定的)void。
- 这意味着我提出的使用 C99 灵活数组的用例将不起作用(这并不奇怪,因为灵活数组不是标准 C++)
- 在最新的 c++ 草案中,它是用一个新关键字 - alignas 定义的(这具有相同的完整类型要求)
- 在我看来,如果 C++ 标准曾经支持 C99 灵活数组,则可以放宽要求(结构与灵活数组的对齐方式不应根据数组元素的数量而改变)
- c++ boost::alignment_of
- 主要是 tr1 替代品
- 似乎专门用于 void 并在这种情况下返回 0 (这在 c++ 草案中是禁止的)
- 开发人员注意:严格来说,您应该只依赖 ALIGNOF(T) 的值是 T 的真实对齐的倍数,尽管在实践中它确实在我们所知道的所有情况下计算正确的值。
- 我不知道这是否适用于灵活的数组,它应该(通常可能不起作用,这解决了我平台上的编译器内在问题,所以我不知道它在一般情况下会如何表现)
- Andrew Top 提出了一个简单的模板解决方案,用于计算答案中的对齐方式
- 这似乎与 boost 所做的非常接近(如果它小于我所看到的计算对齐,boost 将另外返回对象大小作为对齐)所以可能同样的通知适用
- 这适用于灵活的数组
- 使用 Windbg.exe 找出符号的对齐方式
- 不是编译时间,特定于编译器,没有测试它
- 在包含该类型的匿名结构上使用 offsetof
- 查看答案,不可靠,不可移植 c++ non-POD
- 编译器内在函数,例如。MSVC __alignof
- 使用灵活的数组
- alignof 关键字在最新的 c++ 草案中
如果我们想使用“标准”解决方案,我们仅限于 std::tr1::alignment_of,但如果您将 c++ 代码与 c99 的灵活数组混合使用,这将不起作用。
正如我所见,只有 1 个解决方案 - 使用旧的 struct hack:
struct S
{
a_t a;
b_t b;
c_t c[1]; // "has" more than 1 member, strictly speaking this is undefined behavior in both c and c++ when used this way
};
在这种情况下(以及所有其他情况),不同的 c 和 c++ 标准及其日益增长的差异是不幸的。
另一个有趣的问题是(如果我们不能以可移植的方式找出结构的对齐方式)可能最严格的对齐要求是什么。我可以找到几个解决方案:
- boost(内部)使用多种类型的联合,并在其上使用 boost::alignment_of
- 最新的 c++ 草案包含 std::aligned_storage
- 对于大小不大于 Len 的任何 C++ 对象类型,default-alignment 的值应是最严格的对齐要求
- 所以
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value
应该给我们最大的对齐 - 仅草稿,尚不标准(如果有的话),
tr1::aligned_storage
没有此属性
- 所以
- 对于大小不大于 Len 的任何 C++ 对象类型,default-alignment 的值应是最严格的对齐要求
对此的任何想法也将不胜感激。
我已暂时取消选中已接受的答案,以获得对新子问题的更多可见性和输入