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


相关推荐
Sarvartha2 小时前
final 关键字
java·开发语言
2601_952047792 小时前
单一策略深度教程:用轻易云把集成任务的报错实时推送到钉钉机器人
java·机器人·钉钉
fpcc2 小时前
c++编程实践—堆和栈越界调试
c++
yi0112 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
_upupup2 小时前
Linux的调试工具——gdb/cgdb
linux·服务器
数据狐(Datafox)2 小时前
淘宝图片搜索 API 落地实战:基于以图搜货搭建跨境电商选品系统
java·大数据·微服务
JeJe同学3 小时前
Docker镜像导入、容器启动
linux·运维·docker
Jason_zhao_MR3 小时前
Linux与实时控制如何兼得
linux·嵌入式硬件·机器人·工业控制
weiabc3 小时前
MSYS2 UCRT64 + g++ C++ 中文输出乱码 完整全过程
c++