Рассматривается реализация структурных типов данных union
, enum
, и struct
. Так же рассматривается заполнение структур и реализацию битового поля.
Unions (обьединение)
union
другого типа, результат может быть предсказан на основе исходного типа.
Enumerations (перечисление)
enum
реализуется наименьшим числовым типом который содержит диапазон перечисления enum
.
--enum_is_int
, если enum
перечисление содержит только положительные значения перечислителя, тип хранения перечисления является первым беззнаковым типом из следующего списка в соответствии с диапазоном перечислений в перечислении enum
.В других режимах, и в случаях когда enum
содержит отрицательные значения перечислителя,тип хранения enum
является первым из следующего, согласно диапазону перечисления в перечислителе enum
:
-
unsigned char
если не используется--enum_is_int
-
signed char
если не используется--enum_is_int
-
unsigned short
если не используется--enum_is_int
-
signed short
если не используется--enum_is_int
signed int
-
unsigned int
кроме Си с--strict
-
signed long long
кроме Си с--strict
-
unsigned long long
кроме Си с--strict
.
Примечание
- В RVCT 4.0, тип хранилища
enum
являющийся первым беззнаковым типом из списка применяется только в режиме GNU (--gnu
). - В ARM® Compiler 4.1 и выше, тип хранения перечисления
enum
тип хранения перечисления, являющийся первым беззнаковым типом из списка, применяется независимо от режима.
enum
таким образом может уменьшать размер данных. Опция командной строки --enum_is_int
lделает основной тип enum
наименьшой шириной int
.
Примечание
Care must be taken when mixing translation units that have been compiled with and without the --enum_is_int
option, and that share interfaces or data structures.
int
s. That is, they must be in the range -2147483648 to +2147483647, inclusive. A warning is issued for out-of-range enumerator values:
#66: enumeration value is out of "int" range
unsigned
int
, long long
, or unsigned long
long
.
armcc --diag_error=66 ...
Structures (структуры)
- все структуры Си
- все C++ структуры и классы не использующие виртуальные или базовые классы.
sizeof()
возвращает размер структуры включающая заполнение.
- Структуры которые определены как
static
илиextern
заполняются нулями. - Структуры в стеке или куче, например которые определены с помощью
malloc()
илиauto
, заполняются тем что хранилось в памяти ранее. Вы не можете использовать функциюmemcmp()
для сравнения содержимого структур определенных таким образом.
--remarks
для просмотра сообщений генерируемых компилятором когда он вставляет дополнения в структуру struct
.
struct { int x; } X = { };
Bitfields (битовое поле)
- Little-endian
- Самые низкие адресации являются наименее значимыми.
- Big-endian
- Самые низкие адресации являются наиболее значимыми.
Примечание
In strict 1990 ISO Standard C, the only types permitted for a bit field are int
, signed int
, and unsigned int
. For non-int
bitfields, the compiler displays an error.
В строгом стандарте ISO стандартного стандарта 1990 года единственными типами, разрешенными для битового поля, являются int
, signed int
, и unsigned int
. Для не —int
битового поля компилятор отображает ошибку.
signed
или unsigned
квалификаторов, рассматривается как unsigned
. Для примера, int x:10
выделяется как целое число без знака размером 10 бит.
struct X { int x:10; int y:20; };
struct X { int x:10; int y:20; int z:5; };
Компилятор заполняет оставшиеся два бита для первого контейнера и назначает новый целочисленный контейнер для z.
Контейнеры битого поля могут перекрывать друг друга, например:
struct X { int x:10; char y:2; };
char
. Не существует подходящего контейнера, поэтому компилятор выделяет новый правильно выровненный контейнерchar
.
int
имеет два бита, выделенных для x, и 6 бит нераспределены. Компилятор выделяет контейнер char
начиная со второго байта предыдущего int
контейнера, пропускает первые два бита, которые выделены для x, и выделяет два бита в y.
struct X { int x:10; char y:8; };
Примечение
int
к структуре и она примет следующий вид:
struct X { int x:10; char y:8; int z:5; }
int
, начинающийся в том же месте, что и контейнер int x:10
, и выделяет байт-выровненный char
и 5-битное битовое поле как показано ниже:
Примечание
В качестве оптимизации компилятор может перезаписывать биты дополнений в контейнере с неопределенными значениями при записи битового поля. Это не влияет на обычное использование битовых полей.
Packing and alignment of bitfields (упаковка и выравнивание битовых полей)
__attribute__((aligned(n)))
делает битовое поле n-байт выравненным, не только его контейнер, but the bitfield is aligned to the packed alignment at most. It is ignored on bitfields in __packed
and __attribute__((packed))
structs.
#pragma pack(2) /* Контейнер b должен начинаться с границы выравнивания 2 байта и должен * иметь размер не больше, чем тип контейнера, в этом случае размер * короткий. Контейнер b не может начинаться со смещения 0 (перекрывается с a) *, так как бит b будет начинаться со смещения 2 и не будет полностью лежать * внутри контейнера. Поэтому контейнер для b должен начинаться со смещения * 2. * * Data layout: 0x11 0x00 0x22 0x22 * Container layout:| a | | b | */ struct { char a; short b : 16; } var1 = { 0x11, 0x2222 }; /* контейнер b может быть до 4 байт. Его размер должен быть 2 или 4 байта, так как они являются кратны* ми выравниванию, которые не больше размера контейнера. При использовании 4 байтового контейнера *, начинающегося с 0, битовое поле b может начинаться со смещения 1 и полностью лежать * внутри контейнера. * * Data layout: 0x11 0x22 0x22 0x00 * Container layout:| a | * | b | */ struct { char a; int b : 16; } var2 = { 0x11, 0x2222 };
8*sizeof(container-type)-1
.
struct A { int z:17; }; // sizeof(A) = 4, alignment = 4 struct A { __packed int z:17; }; // sizeof(A) = 3, alignment = 1 __packed struct A { int z:17; }; // sizeof(A) = 3, alignment = 1
struct A { char y:1; int z:31; }; // sizeof(A) = 4, alignment = 4 struct A { char y:1; __packed int z:31; }; // sizeof(A) = 4, alignment = 1 __packed struct A { char y:1; int z:31; }; // sizeof(A) = 4, alignment = 1
struct A { char y:1; int z:32; }; // sizeof(A) = 8, alignment = 4 struct A { char y:1; __packed int z:32; }; // sizeof(A) = 5, alignment = 1 __packed struct A { char y:1; int z:32; }; // sizeof(A) = 5, alignment = 1
struct A { int x; char y:1; int z:31; }; // sizeof(A) = 8, alignment = 4 struct A { int x; char y:1; __packed int z:31; }; // sizeof(A) = 8, alignment = 4 __packed struct A { int x; char y:1; int z:31; }; // sizeof(A) = 8, alignment = 1
struct A { int x; char y:1; int z:32; }; // sizeof(A) = 12, alignment = 4 [1] struct A { int x; char y:1; __packed int z:32; }; // sizeof(A) = 12, alignment = 4 [2] __packed struct A { int x; char y:1; int z:32; }; // sizeof(A) = 9, alignment = 1
struct example1 { int a : 8; /* 4-byte container at offset 0 */ __packed int b : 8; /* 1-byte container at offset 1 */ __packed int c : 24; /* 3-byte container at offset 2 */ }; /* Total size 8 (3 bytes tail padding) */;
struct example2 { __packed int a : 8; /* 1-byte container at offset 0 */ __packed int b : 8; /* 1-byte container at offset 1 */ int c : 8; /* 4-byte container at offset 0 */ }; /* Total size 4 (No tail padding) */
struct example3 { int a : 8; /* 4-byte container at offset 0 */ __packed int b : 32; /* 4-byte container at offset 1 */ __packed int c : 32; /* 4-byte container at offset 5 */ int d : 16; /* 4-byte container at offset 8 */ int e : 16; /* 4-byte container at offset 12 */ int f : 16; /* In previous container */ }; /* Total size 16 (No tail padding) */
Оставить ответ
Вы должны быть авторизованы чтобы размещать комментарии.