Есть ли прагма для того, чтобы не заботиться о макете структуры / класса? Если нет, то почему?

Есть разные pragmas для управления макетом структуры / класса, например 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) распределяются так, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных с различным контролем доступа не определен

Имейте в виду, что переупорядочение членов изменяет порядок, в котором будут вызываться конструкторы и деструкторы подобъектов, и, возможно, другие вещи. Кажется чрезвычайно рискованным даже с учетом прагмы для компилятора вносить подобные изменения за кулисы (что, если у вас есть член, который зависит от инициализации другого члена).

Другие вопросы по тегам