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

StackOverflow https://stackoverflow.com/questions/281045

  •  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{};

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top