C语言共用(同)体/联合体(union)详解

一. 什么是共同体?

共同体(Union)是C语言中一种特殊的数据结构,它的所有成员共享同一块内存空间。与结构体(Struct)不同,结构体的每个成员有独立的内存空间,而共同体的所有成员覆盖同一段内存。这意味着,共同体在任意时刻只能存储其中一个成员的值。


二. 为什么需要共同体?

共同体的主要目的是节省内存,适用于以下场景:

  • 需要存储不同类型的数据,但每次只用其中一种。
  • 处理硬件寄存器(如嵌入式开发)。
  • 解析网络协议中的二进制数据。
  • 需要灵活操作内存(如底层开发)。

三. 如何使用共同体?

1.定义共同体

使用 union 关键字定义共同体,格式如下:

union UnionName {
    数据类型 成员1;
    数据类型 成员2;
    ...
};

示例:定义一个可以存储整数、浮点数或字符串的共同体

#include <stdio.h>
#include <string.h>

// 定义共同体
union Data {
    int i;          // 整数
    float f;        // 浮点数
    char str[20];   // 字符串
};

2.声明变量

共同体变量的声明方式与结构体类似:

union Data data1, data2;  // 声明两个共同体变量

3.赋值与访问

共同体的成员通过点运算符(.)访问,但每次只能给一个成员赋值,新值会覆盖旧值。

示例:赋值与访问

int main() {
    union Data data;

    // 存储整数
    data.i = 10;
    printf("data.i: %d\n", data.i);  // 输出: 10

    // 存储浮点数(覆盖之前的整数)
    data.f = 3.14;
    printf("data.f: %.2f\n", data.f);  // 输出: 3.14

    // 存储字符串(覆盖之前的浮点数)
    strcpy(data.str, "Hello");
    printf("data.str: %s\n", data.str);  // 输出: Hello

    return 0;
}

4.内存大小

共同体的大小等于其最大成员的大小。例如:

printf("Size of union: %lu bytes\n", sizeof(union Data)); 
// 输出: 20 bytes(因为 char str[20] 占用 20 字节)

四、代码示例详解

完整示例:共同体的定义与使用

#include <stdio.h>
#include <string.h>

// 定义共同体
union Money {
    int moneyi;         // 整数
    double moneyd;      // 双精度浮点数
    char moneystr[100]; // 字符串
};

int main() {
    union Money money;

    // 存储整数
    money.moneyi = 100;
    printf("整数: %d\n", money.moneyi);

    // 存储双精度浮点数(覆盖之前的整数)
    money.moneyd = 100.111;
    printf("浮点数: %.3lf\n", money.moneyd);

    // 存储字符串(覆盖之前的浮点数)
    strcpy(money.moneystr, "100万");
    printf("字符串: %s\n", money.moneystr);

    // 打印内存地址(验证共享内存)
    printf("moneyi 地址: %p\n", &money.moneyi);
    printf("moneyd 地址: %p\n", &money.moneyd);
    printf("moneystr 地址: %p\n", &money.moneystr);

    // 打印共同体大小
    printf("共同体大小: %lu 字节\n", sizeof(money));

    return 0;
}

运行结果:

整数: 100
浮点数: 100.111
字符串: 100万
moneyi 地址: 0x7ffee4b3c8a0
moneyd 地址: 0x7ffee4b3c8a0
moneystr 地址: 0x7ffee4b3c8a0
共同体大小: 104 字节

关键点:

  • 所有成员的内存地址相同,说明它们共享同一块内存。
  • 共享内存的大小由最大成员决定(char moneystr[100] 占 100 字节,加上对齐后总大小为 104 字节)。

⚠️ 重要警告
同一时刻只能使用一个成员!修改一个成员会覆盖其他成员的值。

五. 注意事项

  1. 数据覆盖:每次赋值会覆盖之前的值,因此要确保访问的是最后一次赋值的成员。
  2. 初始化:共同体变量在定义时只能初始化第一个成员。
  3. 类型安全:使用共同体时需明确当前存储的是哪种类型的数据,否则可能导致未定义行为。
  4. 应用场景:适合需要灵活存储不同类型数据且内存有限的场景,如嵌入式系统或网络协议解析。

六、特点

#include <stdio.h>
#include <string.h>

union UnionDemo {
    int num;
    float f;
    char text[6];
};

int main() {
    union UnionDemo u;
    printf("共用体大小:%zu 字节\n", sizeof(u));

    // 1. 存入整数并读取
    u.num = 0x12345678;
    printf("存入整数后:num=0x%X\n", u.num);  // 正确访问方式

    // 2. 存入浮点数并读取
    u.f = 3.14f;
    printf("存入浮点数后:f=%.2f\n", u.f);    // 正确访问方式

    // 3. 存入字符串并读取
    strcpy_s(u.text, sizeof(u.text), "Hi");  // 或者使用 strncpy
    printf("存入字符串后:text=%s\n", u.text); // 正确访问方式

    // 演示错误访问方式(不要这样做)
    printf("错误访问示例:num=0x%X, f=%.2f\n", u.num, u.f);

    return 0;
}

七. 总结

共同体是C语言中一种强大的工具,通过共享内存实现高效的数据存储。虽然它的使用需要谨慎(因为数据会被覆盖),但在特定场景下(如硬件编程、数据解析)能显著优化内存使用。掌握共同体的定义、使用方法和注意事项,能帮助你编写更高效的C程序!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值