命名空间
变体
操作

联合声明

来自 cppreference.cn
< c‎ | language

联合体是一种类型,由一系列成员组成,这些成员的存储空间相互重叠(与结构体相反,结构体是一种类型,由一系列成员组成,这些成员的存储空间按顺序分配)。在任何时候,联合体中最多只能存储一个成员的值。

联合体的类型说明符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) 形式后未跟 ;(即不是前向声明),则不允许使用。

[编辑] 解释

联合体的大小仅为容纳其最大成员所需的大小(也可能添加额外的未命名尾部填充)。其他成员与该最大成员的一部分分配在相同的字节中。

指向联合体的指针可以强制转换为指向其每个成员的指针(如果联合体具有位域成员,则指向联合体的指针可以强制转换为指向位域的底层类型的指针)。同样,指向联合体的任何成员的指针都可以强制转换为指向封闭联合体的指针。

如果用于访问联合体内容的成员与上次用于存储值的成员不同,则存储的值的对象表示将被重新解释为新类型的对象表示(这称为类型双关)。如果新类型的大小大于上次写入类型的大小,则多余字节的内容是未指定的(并且可能是陷阱表示)。在 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 应用于 已发布行为 正确行为
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++ 文档 关于 联合声明