如果已知结构体成员的对齐方式,能否找到结构体类型的对齐方式?
例如:
struct S
{
a_t a;
b_t b;
c_t c[];
};
S = max(alignment_of(a), alignment_of(b), alignment_of(c))的对齐方式是什么?
在搜索互联网时,我发现“对于结构化类型,其元素中最大的对齐要求确定了结构的对齐方式”(来自每个程序员都应该知道的内存知识),但我在标准中(确切地说是最新草案)没有找到任何类似的内容。
编辑: 非常感谢所有的答案,特别是Robert Gamble,他为原始问题提供了一个非常好的答案,以及其他贡献者。
简而言之:
为了确保结构成员的对齐要求,结构的对齐方式必须至少与其最严格的成员的对齐方式一样严格。
至于确定结构的对齐方式,提出了几个选项,并经过一些研究,这就是我找到的内容:
- 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++非POD中不可移植
- 编译器内部函数,例如MSVC __alignof
- 适用于柔性数组
- alignof关键字在最新的c++草案中
如果我们想使用“标准”解决方案,我们只能使用std :: tr1 :: alignment_of,但如果将c ++代码与c99的灵活数组混合使用,则无法正常工作。
在我看来,只有一个解决方案-使用旧的结构体技巧:
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
};
另一个有趣的问题是(如果我们无法以可移植的方式找出结构的对齐方式),最严格的对齐要求是什么。我能找到一些解决方案:
- boost(内部)使用各种类型的联合,并在其上使用boost::alignment_of - 最新的C++草案包含std::aligned_storage - 默认对齐值应为大小不大于Len的任何C++对象类型的最严格对齐要求
- 所以std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value应该给我们最大的对齐方式 - 草案而非标准(如果有的话),tr1::aligned_storage没有这个属性
任何关于此的想法也将不胜感激。
我暂时取消了采纳的答案,以便更多地关注并获得有关新的子问题的输入。