Почему компиляторы 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 гарантирует, что типобезопасный код никогда не сломается.
Я думаю, что такое правило может иметь смысл, потому что я считаю более естественным группировать членов структуры по их содержимому, а не по типам. Также компилятору легче выбрать лучший порядок, чем мне, когда у меня много внутренних структур. Оптимальная компоновка может быть даже такой, которую я не могу выразить безопасным для типов способом. С другой стороны, кажется, что это делает язык более сложным, что, конечно, является недостатком.
Обратите внимание, что я не говорю об изменении языка - только если он мог (/ должен) быть разработан по-другому.
Я знаю, что мой вопрос является гипотетическим, но я думаю, что обсуждение дает более глубокое понимание более низких уровней машинного и языкового дизайна.
Я здесь новичок, поэтому я не знаю, стоит ли мне создавать новый вопрос для этого. Пожалуйста, скажите мне, если это так.