Существуют различные pragma
для управления компоновкой struct/class, например, pragma pack
. Но, насколько я знаю, нет pragma
для того, чтобы сказать: "Меня не волнует макет. Он внутренний, код не полагается на него. Заменяйте его для лучшей производительности/размера". AFAIK, это типичный случай, и во многих случаях он может улучшить производительность и размер. Кроме того, даже если программист был достаточно осторожен, чтобы переупорядочить его для производительности/размера, у другой целевой архитектуры может быть другой оптимальный макет.
Изменить: уточнить, я говорю о порядке членов. Прокладка уже контролируема.
Кроме того, PVS-Studio имеет соответствующее сообщение. Это то, о чем я говорю - почему это невозможно сделать компилятором с pragma
?
Такая прагма будет разрешена стандартом языка, но я не знаю ни одного компилятора, который реализует такую вещь.
В C поведение #pragma
указано в разделе 6.10.6 стандарта (ссылка относится к последнему черновику):
Директива предварительной обработки формы
# pragma pp-tokens optnew-line
где токен предварительной обработкиSTDC
не сразу следует заpragma
в директиве (до любой замены макроса), приводит к тому, что реализация ведет себя определенным образом. Поведение может привести к ошибке перевода или привести к тому, что переводчик или результирующая программа будут вести себя несоответствующим образом. Любая такая прагма, которая не распознается реализацией, игнорируется.
Таким образом, # #pragma
может, по сути, нарушать правила языка.
Соответствующее правило в этом случае состоит в том, что члены структуры выкладываются в том порядке, в котором они объявлены. 6.7.2.1 пункт 15:
Внутри объекта структуры члены небитового поля и единицы, в которых расположены битовые поля, имеют адреса, которые увеличиваются в том порядке, в котором они объявлены. Указатель на объект структуры, соответствующим образом преобразованный, указывает на его первоначальный член (или если этот элемент является битовым полем, а затем блоку, в котором он находится) и наоборот. В структурном объекте может быть неназванное дополнение, но не в начале.
Плохая новость: стандарт C требует, чтобы члены структуры были выложены в том порядке, в котором они объявлены. Первый член должен быть со смещением 0. Может быть произвольное отступы между членами или после последнего, но они не могут быть переупорядочены.
Хорошая новость. Язык позволяет реализации определить #pragma
которая указывает макет, который нарушает вышеуказанное правило.
Плохие новости: насколько я знаю, реализация на самом деле не делает этого. Даже если бы это было так, есть другие реализации, которые этого не делают, поэтому любой код, который использует такую #pragma
, будет не переносимым. (Хотя, по крайней мере, если имя #pragma
уникально, любые компиляторы, которые его не распознают, должны игнорировать его, поэтому ваш код все равно будет компилироваться.)
Это для C. Правила C++ для #pragma
очень похожи на правила C. Я достаточно уверен, что правила C++ для компоновки структуры также похожи на C; Наследование делает вещи немного более сложными.
Язык специально указывает, что члены класса будут упорядочены в памяти так же, как и на каждом уровне доступа (например, private
). Прагма не может отменить это поведение.
См. 9.2/14:
Нестационарные члены данных (non-union) класса с одним и тем же контролем доступа (раздел 11) распределяются так, что более поздние члены имеют более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных с различным контролем доступа неуточнен
Имейте в виду, что члены, переупорядочивающие, меняют порядок, в котором будут называться конструкторы и деструкторы субъектов, и, возможно, другие вещи. Кажется крайне рискованным даже при условии, что компилятор может сделать такие изменения за кулисами (что, если у вас есть член, который зависит от инициализации другого участника).