联合声明
来自 cppreference.cn
联合是一种类型,由一系列成员组成,这些成员的存储空间重叠(与结构体不同,结构体是由一系列成员组成的类型,这些成员的存储空间按顺序分配)。在任何给定时间,联合中最多只能存储其中一个成员的值。
联合的类型说明符与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 起) |
[编辑] 关键字
[编辑] 注意
有关结构体和联合初始化规则,请参阅结构体初始化。
[编辑] 示例
运行此代码
#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++ 文档,关于联合声明
|