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


相关推荐
可涵不会debug2 分钟前
【C++】在线五子棋对战项目网页版
linux·服务器·网络·c++·git
栗子~~3 分钟前
基于quartz,刷新定时器的cron表达式
java
AI+程序员在路上4 分钟前
C#调用c++dll的两种方法(静态方法和动态方法)
c++·microsoft·c#
吴秋霖8 分钟前
最新百应abogus纯算还原流程分析
算法·abogus
杨过姑父10 分钟前
Servlet3 简单测试
java·servlet
chengxuyuan6666623 分钟前
python基础语句整理
java·windows·python
一只会飞的猪_25 分钟前
国密加密golang加密,java解密
java·开发语言·golang
清风-云烟26 分钟前
使用redis-cli命令实现redis crud操作
java·linux·数据库·redis·spring·缓存·1024程序员节
安和昂35 分钟前
effective Objective—C 第三章笔记
java·c语言·笔记
Rm36 分钟前
Linux 防火墙 Systemctl 常用命令速查
linux