Union declaration
Объединение — это тип, состоящий из последовательности членов, чьё хранилище перекрывается (в отличие от структуры, которая является типом, состоящим из последовательности членов, чьё хранилище выделяется в упорядоченной последовательности). Значение не более чем одного из членов может храниться в объединении в любой момент времени.
Спецификатор типа
для объединения идентичен спецификатору типа
struct
за исключением используемого ключевого слова:
Содержание |
Синтаксис
union
attr-spec-seq
(необязательно)
name
(необязательно)
{
struct-declaration-list
}
|
(1) | ||||||||
union
attr-spec-seq
(необязательно)
name
|
(2) | ||||||||
| name | - | имя объединения, которое определяется |
| struct-declaration-list | - | любое количество объявлений переменных, объявлений битовых полей и объявлений статических утверждений. Члены неполного типа и члены функционального типа не допускаются. |
| attr-spec-seq | - |
(C23)
опциональный список
атрибутов
, применяемых к типу объединения, не допускается для
(2)
если такая форма не сопровождается
;
(т.е. не является предварительным объявлением).
|
Объяснение
Объединение имеет размер, достаточный только для хранения своего самого крупного члена (также может быть добавлено дополнительное безымянное завершающее выравнивание). Остальные члены размещаются в тех же байтах, что и часть этого самого крупного члена.
Указатель на объединение может быть приведён к указателю на каждый из его членов (если объединение имеет члены-битовые поля, указатель на объединение может быть приведён к указателю на базовый тип битового поля). Аналогично, указатель на любой член объединения может быть приведён к указателю на содержащее его объединение.
|
Если член, используемый для доступа к содержимому объединения, не совпадает с членом, который последним использовался для сохранения значения, объектное представление сохраненного значения переинтерпретируется как объектное представление нового типа (это известно как type punning ). Если размер нового типа больше размера последнего записанного типа, содержимое избыточных байтов не определено (и может быть trap representation). До C99 TC3 (DR 283) это поведение было неопределенным, но обычно реализовывалось таким образом. |
(since C99) |
|
Аналогично struct, неименованный член union, тип которого является union без name , известен как анонимный union . Каждый член анонимного union считается членом охватывающей struct или union, сохраняя их размещение в памяти. Это применяется рекурсивно, если охватывающая struct или union также является анонимной. struct v { union // anonymous union { struct { int i, j; }; // anonymous structure struct { long k, l; } w; }; int m; } v1; v1.i = 2; // valid v1.k = 3; // invalid: inner structure is not anonymous v1.w.k = 5; // valid Аналогично struct, поведение программы не определено, если union объявлен без каких-либо именованных членов (включая полученные через анонимные вложенные struct или union). |
(since C11) |
Ключевые слова
Примечания
См. инициализация структур для правил инициализации структур и объединений.
Пример
#include <assert.h> #include <stdint.h> #include <stdio.h> int main(void) { union S { uint32_t u32; uint16_t u16[2]; uint8_t u8; } s = {0x12345678}; // s.u32 теперь активный член printf("Union S имеет размер %zu и содержит %x\n", sizeof s, s.u32); s.u16[0] = 0x0011; // s.u16 теперь активный член // чтение из s.u32 или из s.u8 переинтерпретирует представление объекта // printf("s.u8 теперь %x\n", s.u8); // неопределено, обычно 11 или 00 // printf("s.u32 теперь %x\n", s.u32); // неопределено, обычно 12340011 или 00115678 // указатели на все члены union сравниваются равными между собой и с union assert((uint8_t*)&s == &s.u8); // этот union имеет 3 байта завершающего заполнения union pad { char c[5]; // занимает 5 байт float f; // занимает 4 байта, требует выравнивания 4 } p = { .f = 1.23 }; // размер равен 8 для удовлетворения выравнивания float printf("размер union из char[5] и float равен %zu\n", sizeof p); }
Возможный вывод:
Union S имеет размер 4 и содержит 12345678 размер union из char[5] и float равен 8
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| DR 499 | C11 | члены анонимных структур/объединений считались членами охватывающей структуры/объединения | они сохраняют свою структуру памяти |
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.7.2.1 Спецификаторы структур и объединений (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.7.2.1 Спецификаторы структур и объединений (стр: 81-84)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.7.2.1 Спецификаторы структур и объединений (стр: 112-117)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 6.7.2.1 Спецификаторы структур и объединений (стр: 101-104)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 3.5.2.1 Спецификаторы структур и объединений
Смотрите также
|
C++ documentation
для
Union declaration
|