Namespaces
Variants

Union declaration

From cppreference.net

Объединение — это тип, состоящий из последовательности членов, чьё хранилище перекрывается (в отличие от структуры, которая является типом, состоящим из последовательности членов, чьё хранилище выделяется в упорядоченной последовательности). Значение не более чем одного из членов может храниться в объединении в любой момент времени.

Спецификатор типа для объединения идентичен спецификатору типа 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)

Ключевые слова

union

Примечания

См. инициализация структур для правил инициализации структур и объединений.

Пример

#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