информация о заполнении структуры

struct abc
{
  char arr[7];
  char arr1[2];
  int i:24;
};

В приведенной выше структуре с помощью оператора sizeof я получил ее размер 12 байт. Но по моим расчетам (может ошибаться) должно быть 16 байт. Почему он дает 12 байт?

Другой вопрос:

В соответствии с пунктом 14 раздела 6.7.2.1 C99.

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

Для конкретной реализации, где я могу получить документацию, описывающую, как конкретный компилятор (например, gcc) вводит заполнение в структуру? Есть ли какое-то общее правило для всех компиляторов для конкретной архитектуры?


person fuzzy    schedule 14.04.2013    source источник
comment
Реализация определена означает, что каждая реализация может делать это так, как они хотят (нет общего правила), но они должны документировать поведение. Таким образом, эта документация должна быть предоставлена ​​соответствующим компилятором, и вы сможете найти ее, если выполните поиск.   -  person Alok Save    schedule 14.04.2013
comment
Почему должно быть 16? Массивы char не нуждаются в выравнивании, а i представляет собой трехбайтовое битовое поле, поэтому 7+2+3=12.   -  person Sergey Kalinichenko    schedule 14.04.2013
comment
Обычно реализации следуют ABI платформы. Любой компилятор, который идет против платформы, обрекает себя на уединенное существование без взаимодействия.   -  person David Heffernan    schedule 14.04.2013
comment
@EF arr — семь байтов, arr1 — два байта, i — три байта.   -  person Sergey Kalinichenko    schedule 14.04.2013


Ответы (2)


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

Конечно, есть атрибут GCC, ms_struct, позволяющий изменить поведение. Более подробно это описано в документации. .

Итак, эта структура имеет размер 16:

struct abc
{
  char arr[7];
  char arr1[2];
  int i:24;
} __attribute__((ms_struct));

Если вы используете параметр gcc_struct по умолчанию, размер равен 12.

Для конкретной реализации, где я могу получить документацию, описывающую, как конкретный компилятор (например, GCC) вводит заполнение в структуру?

Вам необходимо ознакомиться с документацией каждого компилятора. В случае GCC документация говорит:

4.9. Структуры, объединения, перечисления и битовые поля

  • Доступ к члену объекта объединения осуществляется с использованием члена другого типа (C90 6.3.2.3).

    Соответствующие байты представления объекта обрабатываются как объект того типа, который используется для доступ. См. каламбур. Это может быть представление-ловушка.

  • Обрабатывается ли «простое» битовое поле int как битовое поле int со знаком или как битовое поле int без знака (C90 6.5.2, C90 6.5.2.1, C99 6.7.2, C99 6.7.2.1).

    По умолчанию считается целым числом со знаком, но это можно изменить с помощью параметра -funsigned-bitfields.

  • Допустимые типы битовых полей, отличные от _Bool, signed int и unsigned int (C99 6.7.2.1).

    В режиме строгого соответствия никакие другие типы не разрешены.

  • Может ли битовое поле пересекать границу единицы хранения (C90 6.5.2.1, C99 6.7.2.1).

    Определяется ABI.

  • Порядок размещения битовых полей в блоке (C90 6.5.2.1, C99 6.7.2.1).

    Определяется ABI.

  • Выравнивание элементов структур, не являющихся битовыми полями (C90 6.5.2.1, C99 6.7.2.1).

    Определяется ABI.

  • Целочисленный тип, совместимый с каждым перечисляемым типом (C90 6.5.2.2, C99 6.7.2.2).

    Обычно типом является unsigned int, если в перечислении нет отрицательных значений, в противном случае — int. Если указан -fshort-enums, то при наличии отрицательных значений это первый из signed char, short и int, который может представлять все значения, в противном случае это первый из unsigned char, unsigned short и unsigned int, который может представлять все значения. значения.

    Для некоторых целей по умолчанию используется -fshort-enums; это определяется ABI.

Итак, по большому счету, вам нужно выяснить, что такое ABI для вашей платформы. Это действительно разумная вещь для любого компилятора. Если он не размещает структуры в соответствии с ABI, то это делает взаимодействие чрезвычайно сложным.

Что немного странно, так это то, что взгляд GCC на то, что такое ABI в Windows, отличается от реализации MSVC. У меня нет понимания, почему это так.

person David Heffernan    schedule 14.04.2013

Это очень просто.

struct abc
{
  char arr[7];  // occupies 7 bytes
  char arr1[2]; // occupies 2 bytes
  int i:24;     // occupies 3 bytes
};

Теперь в третьем объявлении (из i) требуется только 3 байта. У вас уже есть это следующим образом:

0 1 2 3 // All 4 bytes used for `char arr[7]`
0 1 2 3 // 3 more used for `char arr[7]`, 1 used for `char arr1[2]`
0 1 2 3 // 1 used for `char arr1[2]`, and the remaining 3 bytes will be used for `int i:24`

Но если вы используете int i (без битового поля), он будет потреблять 16 байт, потому что

0 1 2 3 // All 4 bytes used for `char arr[7]`
0 1 2 3 // 3 more used for `char arr[7]`, 1 used for `char arr1[2]`
0 1 2 3 // 1 used for `char arr1[2]`, there are still 3 bytes but we need 4 bytes for an `int`
0 1 2 3 // So the compiler will allocate a new 4 byte chunk for `int i`

Думаю, теперь все ясно.

person surender8388    schedule 14.04.2013
comment
Различные компиляторы имеют 3-байтовое заполнение после arr1 и 1-байтовое заполнение после i. Итак, вопрос, почему это должно быть так? Я думаю, довольно очевидно, как устроена эта структура, если ее размер равен 12. Я не могу придумать другого способа сделать это. - person David Heffernan; 14.04.2013
comment
Это зависит от компилятора, как он управляет своей памятью. В GCC та же структура (упомянутая вами) будет иметь размер 12 байт, в то время как в компиляторе Visual C она будет иметь размер 16 байт. Потому что это зависит от того, как компилятор следует стандарту и реализует его. - person surender8388; 14.04.2013
comment
Ну вполне. В этом суть вопроса. Я совершенно уверен, что @fuzzy может увидеть, как будет устроена 12-байтовая разметка. - person David Heffernan; 14.04.2013