Объявление объединения
Объединение — это тип, состоящий из последовательности членов, области памяти которых перекрываются (в отличие от структуры, которая представляет собой тип, состоящий из последовательности членов, области памяти которых выделяются последовательно). В каждый момент времени в объединении может храниться значение не более чем одного члена.
Спецификатор типа для объединения идентичен спецификатору типа 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), если за ней не следует ; (то есть это не предварительное объявление). |
Пояснение
Размер объединения достаточен для хранения его самого большого члена (также может добавляться дополнительное безымянное замыкающее заполнение). Остальные члены размещаются в тех же байтах, что и этот самый большой член.
Указатель на объединение можно преобразовать в указатель на каждый из его членов (если в объединении есть члены-битовые поля, указатель на объединение можно преобразовать в указатель на базовый тип битового поля). Аналогично, указатель на любой член объединения можно преобразовать в указатель на охватывающее его объединение.
| Если для доступа к содержимому объединения используется не тот член, который последним применялся для сохранения значения, представление объекта сохранённого значения интерпретируется как представление объекта нового типа (это называется переинтерпретацией типа). Если размер нового типа больше размера типа, значение которого было записано последним, содержимое лишних байтов не определено (и может быть ловушечным представлением). До C99 TC3 (DR 283) такое поведение считалось неопределённым, однако на практике оно часто реализовывалось именно таким образом. | (начиная с C99) |
| Как и в случае со структурой, безымянный член объединения, тип которого является объединением без name, называется анонимным объединением. Каждый член анонимного объединения считается членом охватывающей структуры или объединения, сохраняя при этом расположение членов объединения в памяти. Это правило применяется рекурсивно, если охватывающая структура или объединение также является анонимной. 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
Как и в случае со структурой, поведение программы не определено, если объединение определено без именованных членов (включая члены, полученные через анонимные вложенные структуры или объединения). | (начиная с 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 is now the active member
printf("Union S has size %zu and holds %x\n", sizeof s, s.u32);
s.u16[0] = 0x0011; // s.u16 is now the active member
// reading from s.u32 or from s.u8 reinterprets the object representation
// printf("s.u8 is now %x\n", s.u8); // unspecified, typically 11 or 00
// printf("s.u32 is now %x\n", s.u32); // unspecified, typically 12340011 or 00115678
// pointers to all members of a union compare equal to themselves and the union
assert((uint8_t*)&s == &s.u8);
// this union has 3 bytes of trailing padding
union pad
{
char c[5]; // occupies 5 bytes
float f; // occupies 4 bytes, imposes alignment 4
} p = { .f = 1.23 }; // the size is 8 to satisfy float's alignment
printf("size of union of char[5] and float is %zu\n", sizeof p);
}
Возможный вывод:
Union S has size 4 and holds 12345678 size of union of char[5] and float is 8
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C.
| DR | Применяется к | Поведение согласно опубликованному тексту | Корректное поведение |
|---|---|---|---|
| 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++ для объявления объединения |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/language/union