如果已知结构构件的对齐,是否可以找到结构类型的对齐?
例如.对于:
struct S
{
a_t a;
b_t b;
c_t c[];
};
Run Code Online (Sandbox Code Playgroud)
是S = max(alignment_of(a),alignment_of(b),alignment_of(c))的对齐?
在网上搜索我发现"对于结构化类型,其任何元素的最大对齐要求决定了结构的对齐"(在每个程序员应该知道的内存中)但我在标准中找不到任何类似的东西(最新草稿更准确).
编辑: 非常感谢所有的答案,特别是罗伯特·甘博为原始问题提供了一个非常好的答案,以及其他贡献者.
简而言之:
为了确保结构构件的对准要求,结构的对准必须至少与其最严格构件的对准一样严格.
至于确定结构的对齐方式,我们提出了一些选项,经过一些研究,我发现了这个:
如果我们想要使用"标准"解决方案,我们只限于std :: tr1 :: alignment_of,但如果你将c ++代码与c99的灵活数组混合,这将不起作用.
我认为它只有一个解决方案 - 使用旧的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
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下(以及其他所有情况),不同的c和c ++标准及其不断增长的差异是不幸的.
另一个有趣的问题是(如果我们无法以便携方式找出结构的对齐方式)可能的最严格的对齐要求是什么.我可以找到几种解决方案:
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value
应该给我们最大的一致性 tr1::aligned_storage
没有这个属性对此的任何想法也将不胜感激.
我暂时取消选中接受的答案,以获得更多关于新子问题的可见性和输入
Rob*_*ble 26
这里有两个密切相关的概念:
为了确保结构构件的对准要求,结构的对准必须至少与其最严格构件的对准一样严格.我不认为标准中明确说明了这一点,但可以从以下事实中推断出来(在标准中单独列出):
如果结构的对齐方式至少与其每个成员一样严格,则无法创建结构数组,因为某些结构成员的某些元素将无法正确对齐.
现在,编译器必须根据其成员的对齐要求确保结构的最小对齐,但它也可以以比所需更严格的方式对齐对象,这通常是出于性能原因而进行的.例如,许多现代处理器将允许以任何对齐方式访问32位整数,但如果它们未在4字节边界上对齐,则访问可能会明显变慢.
没有可移植的方法来确定处理器对任何给定类型强制执行的对齐,因为语言没有公开这种对齐,尽管由于编译器显然知道目标处理器的对齐要求,因此它可以将此信息公开为扩展.
虽然许多编译器可以选择对对齐提供某种程度的控制,但也没有可移植的方式(至少在C中)来确定编译器如何实际对齐对象.
小智 13
我编写了这种类型的特征代码来确定任何类型的对齐方式(基于已经讨论过的编译器规则).您可能会发现它很有用:
template <class T>
class Traits
{
public:
struct AlignmentFinder
{
char a;
T b;
};
enum {AlignmentOf = sizeof(AlignmentFinder) - sizeof(T)};
};
Run Code Online (Sandbox Code Playgroud)
所以现在你可以去:
std::cout << "The alignment of structure S is: " << Traits<S>::AlignmentOf << std::endl;
Run Code Online (Sandbox Code Playgroud)
以下宏将返回任何给定类型的对齐要求(即使它是结构):
#define TYPE_ALIGNMENT( t ) offsetof( struct { char x; t test; }, test )
Run Code Online (Sandbox Code Playgroud)
注意:我可能在过去的某个时候从微软的标题中借用了这个想法......
编辑:正如Robert Gamble在评论中指出的那样,这个宏不能保证有效.实际上,如果将编译器设置为在结构中打包元素,它肯定不会很好地工作.因此,如果您决定使用它,请谨慎使用.
有些编译器有一个扩展,允许你获得一个类型的对齐(例如,从VS2002开始,MSVC有一个__alignof()
内在的).那些应该在可用时使用.
归档时间: |
|
查看次数: |
14558 次 |
最近记录: |