Всегда ли члены класса / структуры создаются в памяти в порядке их объявления? - PullRequest
41 голосов
/ 11 ноября 2008

Этот вопрос возник у Роба Уокера ответа здесь .

Предположим, я объявляю класс / структуру примерно так:

struct
{ 
    char A;
    int B;
    char C;
    int D;
};

Можно ли предположить, что эти члены будут объявлены именно в этом порядке в памяти, или это зависит от компилятора? Я спрашиваю, потому что я всегда предполагал, что компилятор может делать с ними все, что захочет.

Это приводит к моему следующему вопросу. Если приведенный выше пример вызывает проблемы с выравниванием памяти, почему компилятор не может просто неявно превратить это в нечто подобное:

struct
{ 
    char A;
    char C;
    int B;
    int D;
};

(я в основном спрашиваю о C ++, но мне было бы интересно услышать и ответ C)

Похожие темы

Ответы [ 6 ]

72 голосов
/ 11 ноября 2008

C99 §6.7.2.1 пункт 13 гласит:

Внутри объекта структуры члены без битовых полей и единицы в какие битовые поля имеют адреса это увеличение в порядке, в котором они объявлены.

и продолжает говорить немного больше о заполнении и адресах. Эквивалентный раздел C89 - §6.5.2.1.

C ++ немного сложнее. В стандартах 1998 и 2003 годов есть пункт 12 § 9.2 (пункт 15 в C ++ 11):

Нестатические данные членов (не объединенный) класс, объявленный без промежуточный спецификатор доступа распределены так, чтобы более поздние члены имели более высокие адреса в классе объект. Порядок выделения нестатические члены данных, разделенные спецификатор доступа не указан (11.1). Выравнивание реализации требования могут вызвать два смежных Члены не должны быть распределены сразу после друг друга; так может требования к пространству для управления виртуальные функции (10.3) и виртуальные базовые классы (10,1).

4 голосов
/ 11 ноября 2008

Элементы данных расположены в заявленном порядке. Компилятор может свободно добавлять отступы для организации выравнивания памяти, которое ему нравится (и вы обнаружите, что многие компиляторы имеют множество параметров спецификации выравнивания - полезно, если смешивать биты, скомпилированные разными программами.)

См. Также Почему GCC не оптимизирует структуры? .


Похоже, что этот ответ несколько устарел для C ++. Вы узнаете что-то каждый день. Спасибо Аиб, Неманья.

3 голосов
/ 11 ноября 2008

В принципе, вы можете рассчитывать на это только для классов со стандартным макетом . Строго говоря, стандартная разметка - это вещь C ++ 0x, но на самом деле она просто стандартизирует существующую практику /

2 голосов
/ 11 ноября 2008

Помимо дополнения для выравнивания, никакая оптимизация структуры не разрешена никаким компилятором (который я знаю) для C или C ++. Я не могу говорить о классах C ++, поскольку они могут быть совершенно другим зверем.

Учтите, что ваша программа взаимодействует с кодом системы / библиотеки в Windows, но вы хотите использовать GCC. Вам нужно будет убедиться, что GCC использует идентичный алгоритм оптимизации макета, чтобы все ваши структуры были правильно упакованы перед отправкой их в скомпилированный MS-код.

2 голосов
/ 11 ноября 2008

Я не могу говорить за C ++, но в C порядок гарантированно будет таким же, как в структуре.

0 голосов
/ 11 ноября 2008

Просматривая соответствующие темы справа, я посмотрел на этот вопрос . Я полагаю, что это может быть интересный случай, когда мы думаем об этих проблемах (если только это не является более распространенным, чем я понимаю).

Перефразируя, если у вас есть структура в C, которая выглядит примерно так:

struct foo{};

и подкласс это как в C ++ (с использованием отдельного модуля компиляции):

extern "C" foo;
struct bar: public foo{};

Тогда выравнивание памяти не обязательно будет таким же, как упоминает aib (даже среди компиляторов того же производителя).

...