名稱空間
變體
操作

聯合宣告

來自 cppreference.com
< c‎ | language

聯合是一種型別,由一系列成員組成,這些成員的儲存空間重疊(與結構體不同,結構體是由一系列成員組成的型別,這些成員的儲存空間按順序分配)。在任何給定時間,聯合中最多隻能儲存其中一個成員的值。

聯合的型別說明符struct型別說明符相同,只是使用的關鍵字不同

目錄

[編輯] 語法

union attr-spec-seq (可選) name (可選) { struct-declaration-list } (1)
union attr-spec-seq (可選) name (2)
name - 正在定義的聯合的名稱
struct-declaration-list - 任意數量的變數宣告、位域宣告和靜態斷言宣告。不允許不完整型別和函式型別的成員。
屬性說明序列 - (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 起)

[編輯] 關鍵字

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 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 499 C11 匿名結構體/聯合的成員被視為包含結構體/聯合的成員 它們保留其記憶體佈局

[編輯] 參考

  • C23 標準 (ISO/IEC 9899:2024)
  • 6.7.2.1 結構體和聯合說明符 (p: TBD)
  • C17 標準 (ISO/IEC 9899:2018)
  • 6.7.2.1 結構體和聯合說明符 (p: 81-84)
  • C11 標準 (ISO/IEC 9899:2011)
  • 6.7.2.1 結構體和聯合說明符 (p: 112-117)
  • C99 標準 (ISO/IEC 9899:1999)
  • 6.7.2.1 結構體和聯合說明符 (p: 101-104)
  • C89/C90 標準 (ISO/IEC 9899:1990)
  • 3.5.2.1 結構體和聯合說明符

[編輯] 另請參閱

C++ 文件,關於聯合宣告