Namespaces
Variants

Union declaration

From cppreference.net

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

联合体的 类型说明符 struct 类型说明符完全相同,唯一的区别在于所使用的关键字:

目录

语法

union 属性说明符序列  (可选) 名称  (可选) { 结构体声明列表 } (1)
union 属性说明符序列  (可选) 名称 (2)
name - 正在定义的联合体名称
struct-declaration-list - 任意数量的变量声明、 位域 声明和静态断言声明。不允许使用不完整类型的成员和函数类型的成员。
attr-spec-seq - (C23) 可选的 属性 列表,应用于联合体类型。如果 (2) 形式后不跟随 ; (即非前向声明),则不允许使用。

说明

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

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

如果用于访问联合体内容的成员与最后用于存储值的成员不同,则已存储值的对象表示将被重新解释为新类型的对象表示(这被称为 类型双关 )。如果新类型的大小大于最后写入类型的大小,则超出字节的内容是未指定的(可能是陷阱表示)。在C99 TC3(DR 283)之前,此行为是未定义的,但通常以这种方式实现。

(since C99)

与结构体类似,联合体中类型为无 名称 联合体的未命名成员被称为 匿名联合体 。匿名联合体的每个成员均被视为外层结构体或联合体的成员,同时保持其联合体布局。若外层结构体或联合体同为匿名,此规则递归适用。

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 现在是活跃成员
    printf("Union S has size %zu and holds %x\n", sizeof s, s.u32);
    s.u16[0] = 0x0011;  // s.u16 现在是活跃成员
    // 从 s.u32 或 s.u8 读取会重新解释对象表示
//  printf("s.u8 is now %x\n", s.u8); // 未指定,通常为 11 或 00
//  printf("s.u32 is now %x\n", s.u32); // 未指定,通常为 12340011 或 00115678
    // 指向联合体所有成员的指针与自身及联合体比较时相等
    assert((uint8_t*)&s == &s.u8);
    // 此联合体有 3 字节的尾部填充
    union pad
    {
        char  c[5]; // 占用 5 字节
        float f;    // 占用 4 字节,要求 4 字节对齐
    } p = { .f = 1.23 }; // 大小为 8 以满足 float 的对齐要求
    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 结构和联合说明符(页码:101-104)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 3.5.2.1 结构和联合说明符

参见

C++ 文档 关于 联合声明