Namensräume
Varianten
Aktionen

Union-Deklaration

Von cppreference.com
< c‎ | Sprache

Eine Union ist ein Typ, der aus einer Folge von Membern besteht, deren Speicher überlappt (im Gegensatz zu struct, einem Typ, der aus einer Folge von Membern besteht, deren Speicher in einer geordneten Reihenfolge zugeteilt wird). Der Wert von höchstens einem der Member kann zu einem Zeitpunkt in einer Union gespeichert werden.

Der Typspezifizierer für eine Union ist identisch mit dem struct-Typspezifizierer, mit Ausnahme des verwendeten Schlüsselworts

Inhalt

[bearbeiten] Syntax

union attr-spec-seq (optional) name (optional) { struct-declaration-list } (1)
union attr-spec-seq (optional) name (2)
name - der Name der zu definierenden Union
struct-declaration-list - beliebige Anzahl von Variablendeklarationen, Bitfeld-Deklarationen und static assert-Deklarationen. Member vom unvollständigen Typ und Member vom Funktionstyp sind nicht erlaubt.
attr-spec-seq - (C23)optionale Liste von Attributen, angewendet auf den Union-Typ, nicht erlaubt für (2), wenn diese Form nicht von einem ; gefolgt wird (d.h. keine Vorwärtsdeklaration).

[bearbeiten] Erklärung

Die Union ist nur so groß wie nötig, um ihren größten Member aufzunehmen (zusätzliches, nicht benanntes nachgestelltes Padding kann ebenfalls hinzugefügt werden). Die anderen Member werden in denselben Bytes als Teil dieses größten Members zugeteilt.

Ein Zeiger auf eine Union kann in einen Zeiger auf jeden ihrer Member umgewandelt werden (wenn eine Union Bitfeld-Member hat, kann der Zeiger auf eine Union in den Zeiger auf den zugrundeliegenden Typ des Bitfelds umgewandelt werden). Ebenso kann ein Zeiger auf einen beliebigen Member einer Union in einen Zeiger auf die umschließende Union umgewandelt werden.

Wenn der Member, der zum Zugriff auf den Inhalt einer Union verwendet wird, nicht derselbe ist wie der Member, der zuletzt zum Speichern eines Wertes verwendet wurde, wird die Objektrepräsentation des gespeicherten Wertes als Objektrepräsentation des neuen Typs neu interpretiert (dies ist als Type Punning bekannt). 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 undefiniert (und können eine Trap-Repräsentation sein). Vor C99 TC3 (DR 283) war dieses Verhalten undefiniert, wurde aber üblicherweise so implementiert.

(seit C99)

Ähnlich wie bei struct wird ein unbenannter Member einer Union, deren Typ eine Union ohne name ist, als anonyme Union bezeichnet. Jeder Member einer anonymen Union wird als Member der umschließenden struct oder Union betrachtet, wobei deren Speicherlayout beibehalten wird. Dies gilt rekursiv, wenn die umschließende struct 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 Member definiert wird (einschließlich derjenigen, die über anonyme verschachtelte structs oder Unions erhalten wurden).

(seit C11)

[bearbeiten] Schlüsselwörter

union

[bearbeiten] Hinweise

Siehe struct initialization für die Regeln zur Initialisierung von structs und unions.

[bearbeiten] 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 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);
}

Mögliche Ausgabe

Union S has size 4 and holds 12345678
size of union of char[5] and float is 8

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
DR 499 C11 Member von anonymen structs/unions wurden als Member der umschließenden struct/union betrachtet sie behalten ihr Speicherlayout bei

[bearbeiten] Referenzen

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

[bearbeiten] Siehe auch

C++ Dokumentation für Union-Deklaration