一、Union 联合体的定义

Union 是一种特殊的数据类型,允许在同一个内存位置存储不同的数据类型。其主要特点是:

  1. 共享内存空间:union 类型是共享内存的,以最大的成员的大小作为整个 union 的大小。

  2. 存储地址相同:联合体中的各数据的存储地址都是相同的。

二、为什么要使用 Union?

  1. 节省内存

    • 当多个数据项不会同时使用时
    • 在嵌入式系统等内存受限环境中特别有用
  2. 数据类型转换

    • dev.to 提到可用于类型转换(type punning)
    • 允许以不同方式解释同一块内存
  3. 实际应用场景
    一个银行账户的例子:

    1
    2
    3
    4
    union AccountInfo {
    struct Person personal;
    struct Company business;
    };

    一个账户要么是个人账户,要么是企业账户,不会同时是两种。

三、Union 的关键特性

  1. 内存分配规则

    1
    2
    3
    4
    5
    union U1 {
    int n; // 4字节
    double d; // 8字节
    char s[11]; // 11字节
    }; // 最终大小为16字节(因字节对齐)
  2. 访问规则

  • 同一时间只能使用一个成员
  • 最后写入的成员是当前有效值
  1. 字节对齐
    ddili.org 提醒,union 的大小会受到字节对齐的影响,在32位和64位系统上可能有所不同。

四、使用注意事项

  1. 数据安全
  • 需要清楚知道当前正在使用哪个成员
  • 避免同时访问多个成员
  1. 字节序考虑
  • 在不同系统间传输数据时需要考虑字节序
  • 建议使用明确的类型转换函数
  1. 替代方案
  • C++中可以考虑使用 std::variant
  • 某些场景可以用结构体(struct)代替

五、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
union Data {
int i;
float f;
char str[20];
} data;

// 使用整数成员
data.i = 10;
printf("Integer: %d\n", data.i);

// 使用浮点数成员
data.f = 3.14;
printf("Float: %f\n", data.f);
// 注意:此时 data.i 的值已经被覆盖

六、最佳实践建议

  1. 明确标记当前类型

    1
    2
    3
    4
    5
    6
    7
    8
    struct Value {
    enum { INT, FLOAT, STRING } type;
    union {
    int i;
    float f;
    char* s;
    } data;
    };
  2. 文档化使用意图

  • 清晰注释每个成员的用途
  • 说明何时使用哪个成员
  1. 考虑安全性
  • 添加类型检查机制
  • 在访问前验证当前活动成员

Union 是一个强大的工具,但需要谨慎使用,确保代码的可维护性和安全性。