Возможный дубликат:
Почему GCC не оптимизирует структуры? Почему С++ не упрощает структуру?
Рассмотрим следующий пример на 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/С++ не разрешено это делать. Мой вопрос в том, почему язык был разработан таким образом. В конце концов, мы можем в конечном итоге тратить огромные объемы памяти, и ссылки, такие как struct_ref->b
, не будут заботиться об этой разнице.
РЕДАКТИРОВАТЬ: Спасибо всем за ваши чрезвычайно полезные ответы. Вы очень хорошо объясняете, почему перестройка не работает из-за того, как был разработан язык. Тем не менее, это заставляет меня думать: будут ли эти аргументы по-прежнему держаться, если бы перестановка была частью языка? Скажем, что было определенное правило переупорядочения, из которого нам потребовалось хотя бы то, что
- мы должны только реорганизовать структуру, если это действительно необходимо (ничего не делать, если структура уже "плотная" )
- правило просматривает только определение структуры, а не внутренние внутренние структуры. Это гарантирует, что тип структуры имеет один и тот же макет, независимо от того, является ли он внутренним в другой структуре.
- скомпилированный макет памяти данной структуры предсказуем, учитывая его определение (т.е. правило фиксировано)
Адаптация аргументов одна за другой. Причина:
-
Отображение низкоуровневых данных, "элемент наименьшего удивления": просто напишите свои структуры в жестком стиле самостоятельно (например, в ответе @Perry), и ничего не изменилось (требование 1). Если по какой-то странной причине вы хотите, чтобы внутренняя прокладка была там, вы можете вставить ее вручную, используя фиктивные переменные, и/или могут быть ключевые слова/директивы.
-
Различия в компиляторах: Требование 3 устраняет эту проблему. На самом деле, из комментариев @David Heffernan, кажется, что сегодня у нас есть эта проблема, потому что разные компиляторы используют по-разному?
-
Оптимизация. Весь смысл переупорядочения - оптимизация (памяти). Я вижу здесь много возможностей. Возможно, мы не сможем удалить прописку вместе, но я не вижу, как переупорядочение может каким-либо образом ограничить оптимизацию.
-
Тип кастинга: Мне кажется, что это самая большая проблема. Тем не менее, должны быть пути вокруг этого. Поскольку правила фиксированы на языке, компилятор может выяснить, как члены были переупорядочены, и реагировать соответственно. Как упоминалось выше, всегда будет возможно предотвратить переупорядочение в тех случаях, когда вы хотите получить полный контроль. Кроме того, требование 2 гарантирует, что безопасный код никогда не сломается.
Причина, по которой я думаю, что такое правило может иметь смысл, состоит в том, что я считаю более естественным группировать элементы структуры по их содержанию, чем по их типам. Кроме того, компилятор легче выбрать лучший порядок, чем для меня, когда у меня много внутренних структур. Оптимальный макет может даже быть тем, который я не могу выразить безопасным типом. С другой стороны, казалось бы, язык стал более сложным, что, конечно, является недостатком.
Обратите внимание, что я не говорю об изменении языка - только если он (/должен) был разработан по-разному.
Я знаю, что мой вопрос гипотетический, но я думаю, что обсуждение дает более глубокое понимание нижних уровней машинного и языкового дизайна.
Я здесь совершенно новый, поэтому я не знаю, должен ли я задать новый вопрос для этого. Скажите, пожалуйста, если это так.