Почему компиляторы C не могут переставлять элементы структуры для устранения отступов выравнивания? [Дубликат]

Возможный дубликат:
Почему GCC не оптимизирует структуры?
Почему C ++ не делает структуру более узкой?

Рассмотрим следующий пример на 32-битной машине x86:

Из-за ограничений выравнивания, следующая структура

struct s1 {
    char a;
    int b;
    char c;
    char d;
    char e;
}

может быть представлен более эффективно с точки зрения памяти (12 против 8 байт), если элементы были переупорядочены, как в

struct s2 {
    int b;
    char a;
    char c;
    char d;
    char e;
}

Я знаю, что компиляторы C / C ++ не могут это делать. Мой вопрос, почему язык был разработан таким образом. В конце концов, мы можем в конечном итоге тратить огромное количество памяти, и такие ссылки, какstruct_ref->b не заботился бы о разнице.

РЕДАКТИРОВАТЬСпасибо всем за ваши чрезвычайно полезные ответы. Вы очень хорошо объясняете, почему перестановка не работает из-за способа, которым был разработан язык. Тем не менее, это заставляет меня задуматься: будут ли эти аргументы сохраняться, если перестановка будет частью языка? Допустим, было определенное правило перестановки, из которого мы требовали, по крайней мере,

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

Обращаясь к вашим аргументам один за другим, я рассуждаю:

Низкоуровневое отображение данных, «элемент наименьшего удивления»: Просто напишите свои структуры в строгом стиле самостоятельно (как в ответе @ Perry), и ничего не изменилось (требование 1). Если по какой-то странной причине вы хотите, чтобы там был внутренний отступ, вы можете вставить его вручную, используя фиктивные переменные, и / или могут быть ключевые слова / директивы.

Отличия компилятора: Требование 3 устраняет эту проблему. На самом деле, из комментариев @David Heffernan, кажется, что у нас сегодня есть эта проблема, потому что разные компиляторы по-разному дополняют?

оптимизация: Весь смысл переупорядочения заключается в оптимизации памяти. Я вижу большой потенциал здесь. Возможно, мы не сможем удалить все отступы вместе, но я не понимаю, как переупорядочение может каким-либо образом ограничить оптимизацию.

Тип литьяМне кажется, что это самая большая проблема. Тем не менее, должны быть способы обойти это. Так как правила зафиксированы в языке, компилятор может выяснить, как члены были переупорядочены, и реагировать соответствующим образом. Как упомянуто выше, всегда будет возможно предотвратить изменение порядка в тех случаях, когда вы хотите получить полный контроль. Кроме того, требование 2 гарантирует, что типобезопасный код никогда не сломается.

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

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

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

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

Ответы на вопрос(11)

Ваш ответ на вопрос