C и C ++ гарантируют, что поля будут размещены в памяти в том же порядке, в котором вы их определили. Для C ++ это гарантировано только для типа POD 1 (все, что было бы допустимо в качестве структуры C [Правка: C89 / 90 - не, например, VLA C99], также будет считаться POD) .
Компилятор может свободно вставлять отступы между членами и / или в конце структуры. Большинство компиляторов дают вам возможность контролировать это (например, #pragma pack(N)
), но это зависит от компилятора.
1 Ну, есть один угловой случай, о котором они не думали, когда он не гарантирован для типа POD - спецификатор доступа нарушает гарантию заказа:
struct x {
int x;
int y;
public:
int z;
};
Это тип POD, но public:
между y
и z
означает, что они теоретически могут быть переупорядочены. Я почти уверен, что это чисто теоретический подход - я не знаю ни одного компилятора, который бы переупорядочивал члены в этой ситуации (и если память не подведет меня даже хуже, чем обычно сегодня, это исправлено в C ++ 0x).
Редактировать: соответствующие части стандарта (по крайней мере, большинство из них) - §9 / 4:
POD-структура - это агрегатный класс, который не имеет энергонезависимой
члены данных типа указатель на член, не POD-структура, не
POD-союз (или массив таких типов) или ссылка, и не имеет
Определяемый пользователем оператор копирования копии и не определяемый пользователем
деструктор.
и §8.5.1 / 1:
Агрегат - это массив или класс (раздел 9) без пользовательских
заявленные конструкторы (12.1), нет частных или защищенных
члены статических данных (пункт 11), без базовых классов (пункт 10)
и без виртуальных функций (10.3).
и §9.2 / 12:
... порядок размещения нестатических данных элементов
разделенный спецификатором доступа не указан (11.1).
Хотя это несколько ограничено §9.2 / 17:
Указатель на объект POD-struct, соответствующим образом преобразованный с использованием
reinterpret_cast, указывает на его начальный член ...
Следовательно, (даже если перед ним стоит public:
, первый определяемый вами элемент должен стоять первым в памяти. Другие члены, разделенные спецификаторами public:
, теоретически могут быть переставлены.
Я должен также указать, что есть место для споров по этому поводу. В частности, в §9.2 / 14 есть также правило:
Два типа POD-struct (раздел 9) совместимы с макетом, если они имеют одинаковое количество нестатических элементов данных, а соответствующие элементы нестатических данных (по порядку) имеют типы, совместимые с макетом (3.9).
Поэтому, если у вас есть что-то вроде:
struct A {
int x;
public:
int y;
public:
int z;
};
Требуется совместимость макета с:
struct B {
int x;
int y;
int z;
};
Я почти уверен, что это было / было предназначено для обозначения того, что члены двух структур должны быть одинаково размещены в памяти. Поскольку второй явно не может переставлять своих членов, первый тоже не должен быть. К сожалению, стандарт никогда не определяет, что означает «совместимость с макетом», что делает аргумент в лучшем случае довольно слабым.