Выравнивание структуры C/C++
В c/ C++ (я предполагаю, что они одинаковы в этом отношении), если у меня есть следующее:
struct S {
T a;
.
.
.
} s;
Гарантируется ли следующее?
(void*)&s == (void*)&s.a;
Или, другими словами, есть ли какая-либо гарантия, что перед первым участником не будет отступов?
2 ответа
В Си, да, это один и тот же адрес. Просто и понятно.
В C++ нет, это не один и тот же адрес. Базовые классы могут (и я подозреваю, что делать) раньше всех членов, а виртуальные функции-члены обычно добавляют где-то скрытые данные в структуру. Еще более запутанно то, что компилятор C++ может также переставлять члены по желанию, если только класс не является стандартным типом макета (хотя я не знаю, что это делает какой-либо компилятор)
Наконец, если структура C++ состоит из стандартных типов макетов, не содержит ни базовых классов, ни виртуальных функций, и все члены имеют одинаковую видимость и, возможно, другие ограничения, которые я забыл, тогда она возвращается к правилам C и требует, чтобы первый член быть по тому же адресу, что и сам объект.
§ 9.2 / 7
Класс стандартного макета - это класс, который:
- не имеет нестатических членов-данных типа нестандартного класса макета (или массива таких типов) или ссылки,
- не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
- имеет одинаковый контроль доступа (пункт 11) для всех нестатических элементов данных,
- не имеет нестандартных макетов базовых классов,
- либо не имеет нестатических членов данных в самом производном классе и не более одного базового класса с нестатическими членами данных, или не имеет базовых классов с нестатическими членами данных, и
- не имеет базовых классов того же типа, что и первый нестатический член данных.
§ 9.2 / 20
Указатель на объект структуры стандартной компоновки, соответствующим образом преобразованный с использованием reinterpret_cast, указывает на его начальный элемент (или, если этот элемент является битовым полем, то на модуль, в котором он находится), и наоборот. [Примечание: Следовательно, в объекте структуры стандартной компоновки может быть безымянный отступ, но не в его начале, что необходимо для достижения соответствующего выравнивания. —Конечная записка]
Да, это.
Гарантируется, что до первого члена структуры в C и в C++ нет заполнения (если это POD).
С цитатой:
(C11, 6.7.2.1p15) "В объекте структуры может быть безымянный отступ, но не в его начале".
C++ цитата:
(C++ 11, 9.2p20) "Следовательно, в объекте структуры стандартной компоновки может быть безымянный отступ, но не в его начале, что необходимо для достижения надлежащего выравнивания"