Рассматривается реализация структурных типов данных 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.
ints. 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) */
Оставить ответ
Вы должны быть авторизованы чтобы размещать комментарии.