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