Ros*_*ina 13 c++ memory-alignment language-lawyer c++11 c++03
给定POD结构(在C++ 03中)或标准布局类型(在C++ 11中),所有成员都具有基本对齐要求,是否保证每个成员根据其对齐要求进行对齐?
换句话说,对于m_k{ m0... mn}标准布局类型的所有成员S,
struct S {
T0 m0;
T1 m1;
...
TN mn;
};
Run Code Online (Sandbox Code Playgroud)
是否保证评估以下表达式true?
(offsetof(S,m_k) % alignof(decltype(S::m_k))) == 0
Run Code Online (Sandbox Code Playgroud)
请给出C++ 03和C++ 11的答案,并引用标准的相关部分.支持C标准的证据也会有所帮助.
我对C++ 03标准(ISO/IEC 14882:2003(E))的阅读是关于POD结构中成员的对齐,除了第一个成员之外,它是静默的.相关段落是:
在规范的语言中,对象是"存储区域":
1.8 C + +对象模型[intro.object]
1.8/1 C++程序中的构造创建,销毁,引用,访问和操作对象.对象是存储区域....
根据对齐要求分配对象:
3.9类型[basic.types]
3.9/5对象类型具有对齐要求(3.9.1,3.9.2).完整对象类型的对齐是表示字节数的实现定义的整数值; 在满足其对象类型的对齐要求的地址处分配对象.
基本类型具有对齐要求:
3.9.1基本类型[basic.fundamental]
3.9.1/3对于每个有符号整数类型,存在相应的(但不同的)无符号整数类型:"unsigned char","unsigned short int","unsigned int"和"unsigned long int",每个它占用相同的存储量,并且具有与相应的有符号整数类型相同的对齐要求(3.9) ; ...
由于"实现对齐要求",可能会发生填充:
9.2班级成员[class.mem]
9.2/12声明没有插入访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.由访问说明符分隔的非静态数据成员的分配顺序未指定(11.1).实现对齐要求可能导致两个相邻成员不会立即分配 ; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).
9.2/12中的"已分配"一词与3.9/5中的"已分配"含义相同吗?规范中"分配"的大多数用法是指动态存储分配,而不是结构内部布局.使用可能在9.2/12中似乎意味着结构成员可能不严格要求3.9/5和3.9.1/3的对齐要求.
POD结构的第一个成员将根据结构的对齐要求进行对齐:
9.2/17指向POD结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然.[ 注意:因此,在POD-struct对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐.]
[重点在上述所有引文中加入.]
Jer*_*fin 10
POD结构的每个元素本身都是一个对象,只能根据这些对象的对齐要求来分配对象.但是,对齐要求可能会发生变化,因为某些东西是另一个对象的子对象([basic.align]/1,2:
1对象类型具有对齐要求(3.9.1,3.9.2),这些要求对可以分配该类型的对象的地址施加限制.的对准是表示在一个给定的对象可以被分配连续地址之间的字节数实现定义整数值.对象类型对该类型的每个对象强制对齐要求; 可以使用对齐说明符(7.6.2)请求更严格的对齐.
2 基本对齐由小于或等于所有上下文中实现所支持的最大对齐的对齐表示,其等于
alignof(std::max_align_t)(18.2).当将类型用作完整对象的类型以及将其用作子对象的类型时,类型所需的对齐可能会有所不同.[ 例如:Run Code Online (Sandbox Code Playgroud)struct B { long double d; }; struct D : virtual B { char c; }何时
D是完整对象的类型B,它将具有类型的子对象,因此必须对其进行适当的对齐long double.如果D作为另一个对象的子对象出现,该对象也具有B虚拟基类,则B子对象可能是不同子对象的一部分,从而减少了子对象的对齐要求D.- 结束示例 ] 运算符的结果alignof反映了对齐要求输入完整对象的情况.
[强调补充]
虽然这些示例通过继承引用子对象,但是规范性措辞一般只引用子对象,所以我相信相同的规则适用,所以一方面你可以假设每个子对象都是对齐的,这样就可以了被访问.另一方面,不,你不能认为这将是alignof给你的相同对齐.
[引用来自N4296,但我相信这同样适用于所有最新版本.当然,C++ 98/03根本没有alignof,但我相信相同的基本原则适用 - 成员将被对齐以便可以使用它们,但是这种对齐要求不一定与它们时相同'被用作独立的对象.]
每种类型有两种不同的对齐要求.一个对应于完整对象,另一个对应于子对象.[basic.align]/2:
当将类型用作完整对象的类型以及将其用作子对象的类型时,类型所需的对齐可能会有所不同.[ 例如:
Run Code Online (Sandbox Code Playgroud)struct B { long double d; }; struct D : virtual B { char c; };何时
D是完整对象的类型B,它将具有类型的子对象,因此必须对其进行适当的对齐long double.如果D作为另一个对象的子对象出现,该对象也具有B作为虚拟基类,则B子对象可能是不同子对象的一部分,从而降低了子对象的对齐要求D.- 结束示例 ] 运算符的结果alignof反映了完整对象情况下类型的对齐要求.
我想不出成员子对象的任何具体例子 - 肯定没有!- ,但是上面的段落承认成员子对象的对齐性弱于alignof屈服,这可能会使你的情况失败.