Подтвердить что ты не робот

Всегда ли члены класса/структуры создаются в памяти в том порядке, в котором они были объявлены?

Это вопрос, который был вызван Rob Walker для ответа здесь.

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

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

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

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

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

(Я в первую очередь спрашиваю о С++, но мне было бы интересно также услышать ответ C)

Связанные темы

4b9b3361

Ответ 1

C99 §6.7.2.1 статья 13 гласит:

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

и далее расскажет немного о дополнениях и адресах. Эквивалентная часть C89 - это §6.5.2.1.

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

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

Ответ 2

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

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


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

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

struct foo{};

и подкласс, как это показано на С++ (с использованием отдельной единицы компиляции):

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

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