命名空间
变体
操作

联合声明

来自 cppreference.cn
< 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++ 文档,关于联合声明