联合声明
来自 cppreference.com
联合体是一种类型,它包含一系列成员,这些成员的存储空间重叠(与结构体不同,结构体是一种包含一系列成员的类型,这些成员的存储空间按顺序分配)。在任何时间,联合体中最多只能存储一个成员的值。
联合体的类型说明符与结构体的类型说明符相同,只是使用的关键字不同。
内容 |
[编辑] 语法
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 联合声明
|