联合体声明

来自cppreference.com
< c‎ | language


联合体是由一序列的成员所组成的类型,各成员的存储重叠(与结构体相反,结构体是由一序列的成员所构成的类型,成员的存储以顺序分配)。在任一时刻,最多能在联合体中存储其一个成员的值。

联合体的类型说明符struct 类型说明符相同,只是所用的关键词有别。

语法

union 属性声明符序列 (可选) 名字 (可选) { 结构体声明列表 } (1)
union 属性声明符序列 (可选) 名字 (2)
名字 - 所定义的联合体的名称
结构体声明列表 - 任意数量的变量声明、位域声明和静态断言声明。不允许不完整类型的成员和函数类型的成员。
属性声明符序列 - (C23)可选的属性列表,应用到联合体类型,若这种形式不后随 ;(即不是前置声明)则对于 (2) 不允许。

解释

联合体只大到足以保有其最大成员(亦可能添加额外的尾随填充字节)。其他成员被分配于与该最大成员一部分相同的字节中。

可以将指向联合体的指针转型为指向它每个成员的指针(若联合体拥有位域成员,则能转型指向联合体的指针为指向位域底层类型的指针)。类似地,指向结构体任何成员的指针都能被转型为指向整个结构体的指针。

若用于访问内容的联合体成员不同于上次用于存储值的成员,则转译被存储值的对象表示为新类型的对象表示(这被称为类型双关)。若新类型的大小大于上次写入的类型大小,则多出的字节内容是未指明的(而且可以是陷阱表示)。C99 TC3(DR 283)之前,此行为未定义,但一般都实现为这种方式。

(C99 起)

类似结构体,类型为不带 名字 的联合体的无名联合体成员被称为匿名联合体。每个匿名联合体的成员被认为是外围结构体或联合体的成员并维持联合体布局不变。若外围结构体或联合体亦为匿名,则递归应用此规则。

struct v {
   union // 匿名联合体
   {
      struct { int i, j; }; // 匿名结构体
      struct { long k, l; } w;
   };
   int m;
} v1;
 
v1.i = 2;   // 合法
v1.k = 3;   // 非法:内层结构体不是匿名的
v1.w.k = 5; // 合法

类似结构体,若不以任何具名成员(包含经由匿名嵌套结构体或联合体获得的成员)定义联合体,则程序行为未定义。

(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

引用

  • C23 标准(ISO/IEC 9899:2024):
  • 6.7.2.1 Structure and union specifiers (第 TBD 页)
  • C17 标准(ISO/IEC 9899:2018):
  • 6.7.2.1 Structure and union specifiers (第 81-84 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 6.7.2.1 Structure and union specifiers (第 112-117 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 6.7.2.1 Structure and union specifiers (第 101-104 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 3.5.2.1 Structure and union specifiers

参阅