Всегда ли члены класса/структуры создаются в памяти в том порядке, в котором они были объявлены?
-
07-07-2019 - |
Вопрос
Это вопрос, который был вызван Роб Уокерответ здесь.
Предположим, я объявляю класс/структуру следующим образом:
struct
{
char A;
int B;
char C;
int D;
};
Можно ли с уверенностью предположить, что эти члены будут объявлены в памяти именно в таком порядке, или это зависит от компилятора?Я спрашиваю, потому что всегда предполагал, что компилятор может делать с ними все, что захочет.
Это приводит к моему следующему вопросу.Если приведенный выше пример вызывает проблемы с выравниванием памяти, почему компилятор не может просто неявно превратить это во что-то вроде этого:
struct
{
char A;
char C;
int B;
int D;
};
(В первую очередь я спрашиваю о C++, но мне было бы интересно услышать и ответ C)
похожие темы
Решение
Пункт 13 §6.7.2.1 C99 гласит:
Внутри структурного объекта, не-бит-поле членов и единиц в какие битовые поля обитают имеют адреса что увеличение в порядке, в котором они объявлены.
и продолжает говорить немного больше о заполнении и адресах.Эквивалентный раздел C89 — §6.5.2.1.
С++ немного сложнее.В стандартах 1998 и 2003 годов есть пункт 12 §9.2 (пункт 15 в C++11):
Нестатические члены данных (несоюзный) класс, объявленный без интервенционирующий спецификатор доступа являются распределены таким образом, чтобы последующие члены имели более высокие адреса внутри класса объект.Порядок выделения нестатические члены данных, разделенные access-specifier не указан (11.1).Согласование осуществления требования могут привести к двум смежным членов, не подлежащих распределению сразу после друг друга;так может требования к площади для управления виртуальные функции (10.3) и виртуальные базовые классы (10.1).
Другие советы
Элементы данных располагаются в объявленном порядке.Компилятор может свободно чередовать заполнение, чтобы организовать желаемое выравнивание памяти (и вы обнаружите, что многие компиляторы имеют множество опций спецификации выравнивания - полезно при смешивании битов, скомпилированных разными программами).
Смотрите также Почему GCC не оптимизирует структуры?.
Похоже, что этот ответ несколько устарел для C++.Вы учитесь чему-то каждый день.Спасибо, Неманья.
В принципе, на это можно рассчитывать только для классов с стандартная планировка.Строго говоря, стандартная компоновка — это вещь C++0x, но на самом деле она просто стандартизирует существующую практику.
Я не могу говорить за C++, но в C порядок в памяти гарантированно соответствует тому, который объявлен в структуре.
Помимо заполнения для выравнивания, ни один компилятор (насколько мне известно) для C или C++ не допускает никакой оптимизации структуры.Я не могу говорить о классах C++, поскольку они могут быть совершенно другим зверем.
Предположим, ваша программа взаимодействует с системным/библиотечным кодом Windows, но вы хотите использовать GCC.Вам нужно будет убедиться, что GCC использует идентичный алгоритм оптимизации макета, чтобы все ваши структуры были правильно упакованы, прежде чем отправлять их в код, скомпилированный MS.
Просматривая соответствующие темы справа, я посмотрел на этот вопрос.Я полагаю, что это может быть интересным крайним случаем при обдумывании этих проблем (если только это не встречается чаще, чем я предполагаю).
Перефразируя, если у вас есть структура в C, которая выглядит примерно так:
struct foo{};
и создайте его подкласс в C++ (используя отдельный модуль компиляции):
extern "C" foo;
struct bar: public foo{};
Тогда выравнивание памяти не обязательно будет одинаковым по причинам айб упоминаний (даже среди компиляторов одного производителя).