Всегда ли члены класса/структуры создаются в памяти в том порядке, в котором они были объявлены?
Это вопрос, который был вызван Rob Walker для ответа здесь.
Предположим, что я объявляю класс/структуру следующим образом:
struct
{
char A;
int B;
char C;
int D;
};
Можно ли предположить, что эти члены будут объявлены точно в этом порядке в памяти или это зависит от компилятора? Я спрашиваю, потому что я всегда предполагал, что компилятор может делать с ним все, что захочет.
Это приводит к моему следующему вопросу. Если приведенный выше пример вызывает проблемы с выравниванием памяти, почему компилятор не может просто превратить это в нечто подобное неявно:
struct
{
char A;
char C;
int B;
int D;
};
(Я в первую очередь спрашиваю о С++, но мне было бы интересно также услышать ответ C)
Связанные темы
Ответы
Ответ 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 (даже среди компиляторов от того же поставщика).