Namespaces
Variants

Union declaration

From cppreference.net

Eine Union ist ein Typ, der aus einer Folge von Mitgliedern besteht, deren Speicher sich überlappt (im Gegensatz zu struct, einem Typ, der aus einer Folge von Mitgliedern besteht, deren Speicher in einer geordneten Sequenz zugewiesen wird). Der Wert von höchstens einem der Mitglieder kann zu einem beliebigen Zeitpunkt in einer Union gespeichert werden.

Der Typ-Spezifizierer für eine Union ist identisch mit dem struct Typ-Spezifizierer, abgesehen vom verwendeten Schlüsselwort:

Inhaltsverzeichnis

Syntax

union attr-spec-seq  (optional) name  (optional) { struct-declaration-list } (1)
union attr-spec-seq  (optional) name (2)
name - der Name der Union, die definiert wird
struct-declaration-list - beliebig viele Variablendeklarationen, Bitfeld -Deklarationen und static_assert-Deklarationen. Elemente unvollständigen Typs und Elemente vom Funktionstyp sind nicht zulässig.
attr-spec-seq - (C23) optionale Liste von Attributen , angewendet auf den Union-Typ, nicht zulässig für (2) wenn diese Form nicht von einem ; gefolgt wird (d.h. keine Vorwärtsdeklaration).

Erklärung

Die Union ist nur so groß wie nötig, um ihr größtes Mitglied aufzunehmen (zusätzlicher unbenannter nachfolgender Auffüllbereich kann ebenfalls hinzugefügt werden). Die anderen Mitglieder werden in denselben Bytes als Teil dieses größten Mitglieds allokiert.

Ein Zeiger auf eine Union kann in einen Zeiger auf jedes ihrer Mitglieder umgewandelt werden (falls eine Union Bitfeld-Mitglieder hat, kann der Zeiger auf die Union in einen Zeiger auf den zugrundeliegenden Typ des Bitfelds umgewandelt werden). Ebenso kann ein Zeiger auf jedes Mitglied einer Union in einen Zeiger auf die umschließende Union umgewandelt werden.

Wenn das Mitglied, das für den Zugriff auf den Inhalt einer Union verwendet wird, nicht mit dem zuletzt zum Speichern eines Werts verwendeten Mitglied übereinstimmt, wird die Objektdarstellung des gespeicherten Werts als Objektdarstellung des neuen Typs reinterpretiert (dies wird als Type Punning bezeichnet). Wenn die Größe des neuen Typs größer ist als die Größe des zuletzt geschriebenen Typs, sind die Inhalte der überschüssigen Bytes nicht spezifiziert (und können eine Trap-Darstellung sein). Vor C99 TC3 (DR 283) war dieses Verhalten undefiniert, wurde jedoch üblicherweise auf diese Weise implementiert.

(since C99)

Ähnlich wie bei struct ist ein unbenanntes Mitglied einer Union, dessen Typ eine Union ohne name ist, bekannt als anonyme Union . Jedes Mitglied einer anonymen Union wird als Mitglied der umschließenden Struktur oder Union betrachtet, wobei ihr Union-Layout beibehalten wird. Dies gilt rekursiv, wenn die umschließende Struktur oder Union ebenfalls anonym ist.

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

Ähnlich wie bei struct ist das Verhalten des Programms undefiniert, wenn eine Union ohne benannte Mitglieder definiert wird (einschließlich derer, die über anonyme verschachtelte Strukturen oder Unions erhalten werden).

(seit C11)

Schlüsselwörter

union

Hinweise

Siehe struct initialization für die Regeln zur Initialisierung von Structs und Unions.

Beispiel

#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 ist nun das aktive Mitglied
    printf("Union S hat Größe %zu und enthält %x\n", sizeof s, s.u32);
    s.u16[0] = 0x0011;  // s.u16 ist nun das aktive Mitglied
    // Lesen von s.u32 oder s.u8 reinterpretiert die Objektdarstellung
//  printf("s.u8 ist nun %x\n", s.u8); // nicht spezifiziert, typischerweise 11 oder 00
//  printf("s.u32 ist nun %x\n", s.u32); // nicht spezifiziert, typischerweise 12340011 oder 00115678
    // Zeiger auf alle Mitglieder einer Union vergleichen sich gleich mit sich selbst und der Union
    assert((uint8_t*)&s == &s.u8);
    // diese Union hat 3 Bytes Nachlauf-Padding
    union pad
    {
        char  c[5]; // belegt 5 Bytes
        float f;    // belegt 4 Bytes, erzwingt Alignment 4
    } p = { .f = 1.23 }; // die Größe ist 8, um das Float-Alignment zu erfüllen
    printf("Größe der Union aus char[5] und float ist %zu\n", sizeof p);
}

Mögliche Ausgabe:

Union S hat Größe 4 und enthält 12345678
Größe der Union aus char[5] und float ist 8

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
DR 499 C11 Mitglieder anonymer Strukturen/Unionen wurden als Mitglieder der umschließenden Struktur/Union betrachtet sie behalten ihr Speicherlayout bei

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.7.2.1 Struktur- und Unionspezifizierer (S.: TBD)
  • C17-Standard (ISO/IEC 9899:2018):
  • 6.7.2.1 Struktur- und Unionspezifizierer (S: 81-84)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.7.2.1 Struktur- und Unionspezifizierer (S: 112-117)
  • C99-Standard (ISO/IEC 9899:1999):
  • 6.7.2.1 Struktur- und Unionspezifizierer (S: 101-104)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 3.5.2.1 Struktur- und Unionspezifizierer

Siehe auch

C++ Dokumentation für Union-Deklaration