【C语言中联合体(共用体)详解】

文章目录


一、前言

在C语言中,联合体(union) ,又称为共用体 ,是一种特殊的数据结构。它与结构体类似,但所有成员共享同一块内存,因此可以在不同时间存储不同类型的数据。联合体在节省内存和处理多态数据时非常有用。


二、联合体的定义与使用

1. 联合体的定义

在C语言中,使用 union 关键字定义联合体,其语法格式如下:

c 复制代码
union 联合体名 {
    数据类型 成员1;
    数据类型 成员2;
    ...
};

示例:

c 复制代码
#include <stdio.h>

union Data {
    int i;
    float f;
    char str[20];
};

int main() {
    union Data data;

    data.i = 10;
    printf("data.i = %d\n", data.i);

    data.f = 220.5;
    printf("data.f = %.2f\n", data.f);

    sprintf(data.str, "Hello, C!");
    printf("data.str = %s\n", data.str);

    // 查看内存大小
    printf("sizeof(data) = %lu 字节\n", sizeof(data));

    return 0;
}

运行结果:

复制代码
data.i = 10  
data.f = 220.50  
data.str = Hello, C!  
sizeof(data) = 20 字节  

说明:

  • data.idata.fdata.str 共享同一块内存
  • 修改其中一个成员后,其他成员的值可能会被覆盖。
  • sizeof(data) 显示的是联合体中占用最大内存的成员的大小,而不是所有成员大小的总和。

2. 联合体与结构体的区别

特性 联合体 union 结构体 struct
内存分配 所有成员共享同一块内存 每个成员独立占据内存
占用内存大小 最大成员的内存大小 所有成员大小的总和
数据存储 同一时刻只能存储一个成员的数据 可同时存储所有成员的数据
数据访问 修改一个成员,其他成员可能被覆盖 修改一个成员不会影响其他成员

示例对比:

c 复制代码
#include <stdio.h>
#include <string.h>

struct StructExample {
    int i;
    float f;
    char str[20];
};

union UnionExample {
    int i;
    float f;
    char str[20];
};

int main() {
    struct StructExample s = {10, 220.5, "Struct"};
    union UnionExample u;

    u.i = 10;
    printf("Union i: %d\n", u.i);
    
    u.f = 220.5;   // 修改 f 会覆盖 i 的值
    printf("Union f: %.2f\n", u.f);
    
    strcpy(u.str, "Union");
    printf("Union str: %s\n", u.str);

    // 查看内存占用
    printf("sizeof(struct) = %lu 字节\n", sizeof(s));
    printf("sizeof(union)  = %lu 字节\n", sizeof(u));

    return 0;
}

运行结果:

复制代码
Union i: 10  
Union f: 220.50  
Union str: Union  
sizeof(struct) = 28 字节  
sizeof(union)  = 20 字节  

三、联合体的使用场景

1. 节省内存

内存紧张 的情况下,联合体可以用于存储多种数据类型,但只在不同时间使用其中一种。例如:

  • 存储网络包的数据时,不同类型的数据包可能占用不同的数据结构。
  • 解析二进制数据时,以多种格式读取同一块内存。

示例:

c 复制代码
#include <stdio.h>

union Packet {
    int id;
    float value;
    char msg[16];
};

int main() {
    union Packet pkt;

    pkt.id = 1234;
    printf("ID: %d\n", pkt.id);

    pkt.value = 56.78;  // 修改浮点数,覆盖 id
    printf("Value: %.2f\n", pkt.value);

    sprintf(pkt.msg, "Hello, World!");
    printf("Msg: %s\n", pkt.msg);

    return 0;
}

2. 位域与联合体

联合体常与位域 结合使用,以实现位操作和数据解析

示例:解析IP地址

c 复制代码
#include <stdio.h>
#include <stdint.h>

union IPAddress {
    uint32_t ip;
    struct {
        uint8_t byte1;
        uint8_t byte2;
        uint8_t byte3;
        uint8_t byte4;
    } bytes;
};

int main() {
    union IPAddress addr;

    addr.ip = 0xC0A80101;  // 192.168.1.1

    printf("IP地址: %d.%d.%d.%d\n",
           addr.bytes.byte1,
           addr.bytes.byte2,
           addr.bytes.byte3,
           addr.bytes.byte4);

    return 0;
}

运行结果:

复制代码
IP地址: 192.168.1.1

解析说明:

  • 使用联合体将 IP 地址表示为整数字节数组
  • 便于在不同格式之间切换。

四、联合体的限制与注意事项

  1. 只能同时存储一个成员的数据
    • 修改一个成员时,其他成员的数据会被覆盖。
  2. 内存对齐问题
    • 联合体在内存中可能存在对齐填充 ,需使用 #pragma pack 控制。
  3. 适用于特定场景
    • 联合体适合节省内存、处理多态数据,不适合存储多个成员的数据。
  4. 无法初始化多个成员
    • C语言中,联合体在声明时只能初始化第一个成员。

示例:

c 复制代码
union Example {
    int x;
    float y;
};

int main() {
    union Example e = {100};    // 初始化第一个成员
    // e = {100, 3.14};         // ❌错误:不能初始化多个成员
    return 0;
}

五、总结

  1. 联合体是一种内存共享的数据结构,适合在不同时刻存储不同类型的数据。
  2. 与结构体不同,联合体的内存大小由最大成员决定
  3. 联合体常用于节省内存、处理多态数据、解析二进制数据等场景。
  4. 使用联合体时需要注意数据覆盖问题,避免误用导致数据丢失。
相关推荐
明天不下雨(牛客同名)12 分钟前
为什么 ThreadLocalMap 的 key 是弱引用 value是强引用
java·jvm·算法
lisw0542 分钟前
DeepSeek原生稀疏注意力(Native Sparse Attention, NSA)算法介绍
人工智能·深度学习·算法
Android洋芋1 小时前
C语言深度解析:从零到系统级开发的完整指南
c语言·开发语言·stm32·条件语句·循环语句·结构体与联合体·指针基础
喝拿铁写前端2 小时前
SmartField AI:让每个字段都找到归属!
前端·算法
莫有杯子的龙潭峡谷2 小时前
3.31 代码随想录第三十一天打卡
c++·算法
Run_Teenage2 小时前
C语言 【初始指针】【指针一】
c语言·开发语言
LuckyLay2 小时前
LeetCode算法题(Go语言实现)_22
算法·leetcode·golang
BingLin-Liu2 小时前
蓝桥杯备考---》贪心算法之矩阵消除游戏
算法·游戏·贪心算法
涛ing3 小时前
【Git “fetch“ 命令详解】
linux·c语言·c++·人工智能·git·vscode·svn
山河君4 小时前
音频进阶学习二十四——IIR滤波器设计方法
学习·算法·音视频·信号处理