19. C语言 共用体(Union)详解

本章目录


前言

在C语言中,共用体(union)是一种特殊的复合数据类型,与结构体(struct)类似,但具备独特的内存共享特性。本文将从共用体的基本概念入手,结合读者笔记中的见解,深入探讨共用体的使用方法、内存布局及实际应用场景,帮助读者掌握这一高效的数据结构。


1. 什么是共用体?

共用体是一种允许多个成员共享同一块内存空间的数据结构。在任何时刻,共用体的所有成员只能有一个成员存储有效数据。这种特性使得共用体特别适合在需要节省内存的场景下使用。

共用体与结构体的区别

特性 结构体 (struct) 共用体 (union)
内存分配 每个成员分配独立的内存空间 所有成员共享同一块内存空间
占用内存大小 所有成员的内存大小之和 最大成员的内存大小
成员访问 可以同时访问多个成员 只能在任一时间访问一个成员

2. 定义共用体

共用体的定义语法类似于结构体,但成员共享内存。例如:

c 复制代码
union Data {
    int i;       // 占用4字节
    float f;     // 占用4字节
    char str[20]; // 占用20字节
};

在这里,Data共用体的大小为其最大成员(char str[20])的大小,即20字节。

示例:定义共用体变量

共用体定义后,可以通过以下方式声明变量:

c 复制代码
union Data data;      // 定义单个变量
union Data dataArr[5]; // 定义共用体数组

可以使用typedef简化定义:

c 复制代码
typedef union {
    int i;
    float f;
    char str[20];
} Data;

Data data; // 定义共用体变量

3. 共用体的内存布局和对齐规则

内存大小计算

共用体的内存大小取决于其最大成员的大小。例如:

c 复制代码
union Example {
    char c;        // 1字节
    double d;      // 8字节
};

此共用体的大小为8字节,因为double占用的空间最大。

字节对齐

内存对齐规则会影响共用体的实际大小。例如:

c 复制代码
union AlignedData {
    char c;        // 1字节
    double d;      // 8字节
    char str[9];   // 9字节
};

在大多数编译器中,该共用体会占用16字节,因对齐规则要求以8字节对齐。

内存对齐原则
  1. 数据成员对齐 :每个成员的对齐规则为其自身大小与#pragma pack指定值的较小者。
  2. 共用体整体对齐 :以最大成员大小与#pragma pack指定值的较小者对齐。
  3. 结构体嵌套对齐:嵌套结构体的对齐以其内部最大成员的对齐要求为准。

4. 访问共用体成员

示例:基本访问

c 复制代码
#include <stdio.h>
#include <string.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: %f\n", data.f);

    strcpy(data.str, "C Programming");
    printf("data.str: %s\n", data.str);

    return 0;
}

注意:由于共用体成员共享内存,修改一个成员会覆盖其他成员的值。因此,共用体应在任何时刻仅使用一个成员。


5. 共用体的实际应用场景

场景1:节省内存

如果有两个结构体,分别表示教师和学生信息,而两者不会同时使用,共用体可以节省内存开销:

c 复制代码
union Person {
    struct {
        char name[20];
        int teacherID;
    } teacher;

    struct {
        char name[20];
        int studentID;
    } student;
};

此共用体的大小为name[20]和studentID(或teacherID)总大小的最大值,而非两者之和。

场景2:网络通信数据包解析

通信协议中,接收的数据包可能有多种格式。使用共用体,可以根据实际格式解析数据:

c 复制代码
union Packet {
    struct {
        int id;
        char message[50];
    } text;

    struct {
        int id;
        float value;
    } sensorData;
};

场景3:判断系统是大端还是小端

利用共用体的内存共享特性,可以方便地判断系统的字节序:

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

union CheckEndian {
    int data;
    char byte;
};

int main() {
    union CheckEndian check;
    check.data = 0x01020304;

    if (check.byte == 0x01) {
        printf("Big-endian system\n");
    } else {
        printf("Little-endian system\n");
    }

    return 0;
}

6. 高效使用共用体的技巧

  1. 只在成员互斥使用时选择共用体 :

    共用体适用于明确知道同时只会使用一个成员的场景。

  2. 注意字节对齐问题 :

    使用共用体时,确保对齐规则与平台一致,避免未定义行为。

  3. 结合结构体实现复杂数据结构 :

    在共用体中嵌套结构体,可灵活处理不同数据格式。


总结

共用体是C语言中功能强大的数据结构,通过共享内存实现了高效的数据管理。本文从共用体的定义、内存模型到高级应用场景,全面解析了这一概念。了解并掌握共用体的使用,可以帮助开发者在内存敏感的场景中设计更高效的程序。希望本文对您有所帮助!


相关推荐
万联WANFLOW几秒前
CVE-2026-98432 等漏洞自查:AI 查出的 Linux、Windows 漏洞,运维怎么确认受不受影响
linux·运维·windows·网络安全
Java后端的Ai之路8 分钟前
【AIAgent开发】-Agent工具封装成CLI(纯干货!!!)
java·javascript·人工智能·agent·cli
OPEN-F15 分钟前
Ubuntu 自动登录后 GNOME 远程桌面连不上?一次登录钥匙环锁定的排查与永久修复
linux·运维·ubuntu
硅基手札25 分钟前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
AntsData37 分钟前
用 12K+ 条亚马逊评论信号,定位机械键盘下一版该改什么
java·大数据·计算机外设
默|笙43 分钟前
【Linux网络】传输层协议TCP(3)滑动窗口、流量控制
linux·网络·tcp/ip
code2cat1 小时前
【随笔】连续批处理:长短请求怎样在迭代之间补位
java·人工智能·后端·大语言模型·vllm
最强小杰1 小时前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
牧羊人.3331 小时前
卷积神经网络之VGG
人工智能·深度学习·神经网络·算法·cnn
Flynn Liang1 小时前
Spring AI 2.0 深度解析:ChatClient、Advisor 链与 MCP——Java 工程师的 AI 落地最优解
java·人工智能·spring·大模型·架构设计·spring ai