Учитывая POD-struct (в С++ 03) или стандартный тип макета (в С++ 11), со всеми членами, имеющими фундаментальное требование выравнивания, верно ли, что каждый член гарантированно выравнивается в соответствии с его требования к выравниванию?
Другими словами, для всех членов m_k
в {m0
... mn
} стандартного типа макета S
,
struct S {
T0 m0;
T1 m1;
...
TN mn;
};
является следующим выражением, гарантируемым для оценки true
?
(offsetof(S,m_k) % alignof(decltype(S::m_k))) == 0
Просьба дать ответы как на С++ 03, так и на С++ 11 и привести соответствующие части стандарта. Полезным будет также поддержка доказательств из стандартов 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-структуры, но не в его начале.]
[Акцент добавлен во всех приведенных выше цитатах.]