Компилятор не может изменять порядок из-за требований стандарта (грубо: уникальные, инкрементные адреса и для классов C++ сгруппированы с помощью модификатора доступа).
Вот почему переупорядочение должно выполняться вручную. Как правило, вам повезло: лучшее выравнивание существующих типов данных означает как меньший размер, так и лучшую производительность, без clnflict.
Однако иногда больший объем данных (элементов) означает более простые инструкции. Например, использование битовых полей для сбривания нескольких байтов означает гораздо более сложный код, существует компромисс между размером кода и размером данных; увеличение внутреннего цикла на 500 байт для сглаживания данных 2k может быть катастрофическим для оптимизации и локальности памяти кода.
Инструменты, такие как PVS Studio, могут выдавать предупреждение , когда порядок элементов структуры субоптимален и может быть улучшен.
[edit2] Что касается «Почему эти правила существуют»:
Tl; Др: это интересно, но не важно, это просто ради любопытства.
Первые (безжалостный копия другого SO ответа) соответствующие разделы стандарта:
Внутри объекта структуры, члены небитовых-полей и единицы, в которых битовых полях располагаются имеют адреса, увеличение порядка, в котором они объявлены. Указатель на объект структуры, соответствующим образом преобразованный, указывает на его первоначальный член (или если этот элемент является битовым полем, а затем блоку, в котором он находится) и наоборот. В структурном объекте может быть неназванное дополнение, но не в начале.
Указатель на объект структуры стандартного макета, соответствующим образом преобразованный с использованием reinterpret_cast, указывает на его начальный член (или если этот элемент является битовым полем, а затем в единицу, в которой он находится) и наоборот. [Примечание. Таким образом, в рамках объекта структуры стандартного макета может быть указано неназванное заполнение, но не в его начале, по мере необходимости, для достижения соответствующего выравнивания. -end примечание]
(Обратите внимание, что это относится к C, C++ является немного более сложным.)
Стандарт мало говорит о причины, большинство из них "образованные догадок" здесь:
Отдельные адреса - это требование, вытекающее из других проблем стандарта.
Создание указателя на структуру, эквивалентное указателю на первый элемент, безусловно, связано с существующей практикой программирования. (Это позволяет «polymorphy данные» в C путем вложения «базовой-структуры» в качестве первого члена «производной структуры»)
сохраняющей порядок, как указано программистом:
The «ванильного предположение» было бы не уничтожать ручную оптимизацию для локализации данных. Включение элемента с наиболее доступным доступом сверху может улучшить локальность внутри структуры (что позволяет лучше кэшировать или сокращать инструкции адресации). Если компилятор переупорядочивает, эти оптимизации могут быть потеряны для меньшего прироста в размере общей структуры.
C++ требует группировку по спецификаторов доступа: (т.е. «все общественные VARS вместе, все защищенные вары вместе, все частные вары вместе): Я никогда не нашел оснований для этого (и я должен сказать, что это было немного удивительно). Я мог представить, что (возможно) целью было позволить реализациям компилятора использовать контроль доступа к аппаратным средствам («этот сегмент кода может не получить доступ к этой части памяти»). OTOH Я не знаю архитектуры, которая позволила бы на этом уровне Я не видел, чтобы спецификаторы доступа считались механизмом secuirty.
Использовать '__attribute__ ((__packed __))' – Mine
Это решение, которое я предполагаю? Так что нет таких проблем с размерами? по умолчанию? (Если нет, то почему? Если да , тогда спасибо :)!) – Narek
Также рассмотрим последствия многомодульной компиляции. Если один модуль переупорядочил их, а другой не ... – Mysticial