聯合宣告
來自 cppreference.com
聯合是一種型別,由一系列成員組成,這些成員的儲存空間重疊(與結構體不同,結構體是由一系列成員組成的型別,這些成員的儲存空間按順序分配)。在任何給定時間,聯合中最多隻能儲存其中一個成員的值。
聯合的型別說明符與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 起) |
[編輯] 關鍵字
[編輯] 注意
有關結構體和聯合初始化規則,請參閱結構體初始化。
[編輯] 示例
執行此程式碼
#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++ 文件,關於聯合宣告
|