C语言联合体union详解:定义、内存对齐与使用场景

一只小鹿
一只小鹿
发布时间:2026-10-13 | 2人浏览过
原创

C语言中的联合体(union)允许不同的数据成员共享同一块内存空间,从而有效节省内存。本文介绍联合体的定义语法、内存布局规则、成员访问时的覆盖现象以及字节对齐原理,并通过实际代码演示其核心行为与应用场景。

结果与目标

掌握C语言联合体(union)的核心概念,理解其“单时间点只能存储一个成员值”的特性,学会计算联合体占用内存的大小(含字节对齐),并能正确应用于需要多类型数据复用内存的场景。

准备条件

了解C语言基础语法,熟悉结构体(struct)、基本数据类型(int, float, char等)以及内存地址的概念。建议使用C编译器(如GCC或Clang)进行代码编译和测试。

第1步:理解联合体的基本概念

联合体是一种特殊的数据类型,其所有成员共享同一段起始地址的内存。这意味着在任何给定时刻,只有最后一个被赋值的成员是有效的,其他成员的值可能会因内存重叠而被覆盖或破坏。

  • 共享内存:所有成员的偏移量均为0。
  • 单一有效性:一次只能安全地读取其中一个成员的值。
  • 内存大小:至少容纳最大的成员,并根据对齐规则填充。

第2步:定义联合体

使用关键字 union 定义联合体,格式类似于结构体,但内存分配逻辑不同。

union [union_tag]
{
    member_definition_1;
    member_definition_2;
    ...
} union_variable_name;

例如,定义一个包含整数、浮点数和字符串的联合体:

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

此时,Data 类型的变量将占据足以容纳最大成员的空间。在上述例子中,str[20] 占用20字节,因此该联合体至少需要20字节的存储空间。

第3步:访问联合体成员

通过成员访问运算符 . 来访问联合体内的成员。需要注意的是,连续赋值不同成员会导致前一个成员的值失效。

#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);  // 输出: 10

    data.f = 220.5;
    printf("data.f : %f\n", data.f);  // 输出: 220.500000

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

    return 0;
}

如果尝试在写入 str 后读取 i 或 f,由于内存已被字符串内容覆盖,读取的结果将是未定义或错误的垃圾值。

第4步:验证联合体内存占用

使用 sizeof 运算符可以查看联合体实际占用的字节数。这通常大于或等于最大成员的大小,具体取决于字节对齐要求。

printf("Memory size occupied by data: %d bytes\n", sizeof(data));

对于之前的 Data 联合体,sizeof(data) 返回 20,因为它是三个成员中最大的(20字节),且20字节通常满足常见架构的对齐要求。

完成判断

程序编译运行正常,能够正确打印各成员值(当按序单独使用时),且 sizeof 返回预期内存大小。成功实现了内存共享的基本操作。

原文有依据的排错:字节对齐与内存大小计算

联合体的大小并非简单地等于最大成员的大小,还受到字节对齐(Alignment)的影响。处理器访问内存时,往往要求数据地址是某个特定值(如4或8)的倍数以提高效率。

分析以下案例:

union U1 {
    char s[9]; // 9字节
    int n;     // 4字节
    double d;  // 8字节
};

union U2 {
    char s[5]; // 5字节
    int n;     // 4字节
    double d;  // 8字节
};

U1 的分析:

  • 最大成员 d 为8字节,s 为9字节。理论上最小需要9字节。
  • 然而,double 通常需要8字节对齐。为了使整个联合体的大小能被其最大成员的对齐字节数(8)整除,编译器会在末尾填充字节。
  • 下一个能被8整除的数是16。因此,sizeof(U1) 为 16 字节。

U2 的分析:

  • 最大成员 d 为8字节,s 为5字节。最小需要8字节。
  • 8本身就能满足8字节对齐的要求,无需额外填充。
  • 因此,sizeof(U2) 为 8 字节。

内存重叠验证:

可以通过指针观察内存中的实际变化。假设 union U1 u1;,执行 u1.n = 1; 后:

  • 内存的前4个字节变为 00 00 00 01(小端序)。
  • 此时读取 u1.s[0],值为 1。
  • 若直接读取 u1.d,由于后4个字节为0,而前4个字节仅为1,构成的double值为极小的非零数或接近0,显示可能为 0.000000 或异常值。

这证明了所有成员确实共享从基地址开始的同一块内存区域。

简要总结

联合体(union)是C语言中用于节省内存的强大工具,特别适合那些在不同时间段需要使用不同类型数据的场景。其核心规则包括:所有成员共享起始地址、同一时间仅一个成员有效、总大小为最大成员大小且需满足对齐要求。开发者在使用时需特别注意类型转换带来的值覆盖风险,并利用 sizeof 和指针技术来排查内存布局问题。

以上就是C语言联合体union定义的详细内容,更多关于C语言数据结构优化的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表