Существуют ли какие-либо гарантии относительно упаковки структур C?

Существуют ли какие-либо гарантии относительно упаковки структур в C?

Например, при условии, что sizeof(double) == 8, гарантируется ли sizeof(struct { double x, y; }) == 16?

Я знаю, что намерение, стоящее за этим вопросом, противоречит строгим правилам псевдонимов, поэтому предположим, что строгое псевдонимы отключены, например. в случае gcc с -fno-strict-aliasing.

Чтобы избежать дальнейших спекуляций: намерение состоит в том, чтобы знать о совместимости структуры с ее явно упакованным аналогом. Обратите внимание, что псевдонимы имеют значение даже в следующем случае: Гарантировано ли, что C-структуры с одинаковыми типами элементов имеют одинаковую компоновку в памяти? . Не нужно беспокоиться о том, что я хочу получить доступ к отдельным байтам.


person Pedro    schedule 05.12.2017    source источник
comment
Ваш вопрос не содержит псевдонимов. Я боюсь видеть, как вы намерены добавить это, так как вы подняли это.   -  person StoryTeller - Unslander Monica    schedule 06.12.2017
comment
Единственная гарантия, о которой я знаю, заключается в том, что перед первым элементом нет заполнения. Не должно быть заполнения, если есть только 1 элемент, поэтому sizeof(struct { double x[2]; }) == 2 * sizeof(double) должно сохраняться.   -  person mch    schedule 06.12.2017
comment
@StoryTeller Я подозреваю, что он планирует получить доступ к байтам структуры с помощью какого-то метода псевдонима, если он знает, как он будет упакован.   -  person Christian Gibbons    schedule 06.12.2017
comment
Является ли это проблемой XY?   -  person Weather Vane    schedule 06.12.2017
comment
@mch Я не уверен, что твой второй пункт верен. Учтите, что указатели на разные типы данных могут иметь разные размеры и ограничения по выравниванию, но все указатели на типы структур и объединений имеют одинаковые требования к размеру и выравниванию. Таким образом, char *, например, может быть больше, чем struct {char} *, и в этом случае структура может потребовать выравнивания больше, чем _Alignof(char).   -  person EOF    schedule 06.12.2017
comment
Целью является совместимость структуры с ее явно упакованным аналогом.   -  person Pedro    schedule 06.12.2017
comment
@WeatherVane: я так не думаю.   -  person Pedro    schedule 06.12.2017


Ответы (1)


Единственное, что говорит стандарт C относительно упаковки структур, это то, что в начале struct не может существовать никакого заполнения. Он не дает никаких гарантий относительно заполнения между полями или в конце.

Раздел 6.7.2.1 стандарта C говорит следующее о структурах:

15 Внутри объекта структуры члены, не являющиеся битовыми полями, и единицы, в которых находятся битовые поля, имеют адреса, которые увеличиваются в порядке их объявления. Указатель на структурный объект, соответствующим образом преобразованный, указывает на его начальный элемент (или, если этот элемент является битовым полем, то на единицу, в которой он находится), и наоборот. В объекте структуры может быть безымянный отступ, но не в его начале.

...

17 В конце структуры или объединения может быть безымянный отступ.

При этом большинство реализаций, как правило, достаточно согласуются с тем, как упаковываются структуры. Неструктурные переменные размером n байта (или массивы таких переменных) будут иметь тенденцию начинаться с границы n байта. Структура внутри структуры, как правило, выравнивается на основе выравнивания ее подполей.

Утерянное искусство упаковки структур C описывает это более подробно.

person dbush    schedule 05.12.2017
comment
Вдобавок к этому существует интересный подход к сериализации под названием Cap'n Proto, целью которого является обеспечение контроля и согласованности упаковки структур на разных машинах, ОС и т. д. С содержанием сообщения (структуры), формализованным схемой и реализованным инструментами и библиотек для Cap'n Proto, сериализация сводится к работе с порядком байтов, что она и делает за вас: так что это очень, очень быстро. Есть что порекомендовать. - person bazza; 06.12.2017