命名空间
变体
操作

联合声明

来自 cppreference.com
< c‎ | 语言

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

联合体的类型说明符与结构体的类型说明符相同,只是使用的关键字不同。

内容

[编辑] 语法

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++ 文档 for 联合声明