C语言共用体union

本文详细介绍了C语言中的共用体(union)概念,包括其定义格式、与结构体(struct)的区别以及内存占用规则。通过实例展示了共用体成员之间如何相互影响,并提供了一个在学生信息和教师信息管理中应用共用体的案例,解释了如何利用共用体节省存储空间并灵活处理不同类型的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来回顾一下结构体(struct)是一种构造类型和复杂类型,他可以包含多个不同类型的成员。在C语言中,在C语言中还有一种和结构体非常类似用法的一种语法,叫做共用体union。

定义格式

union 共用体名{

成员列表

};

struct和union的区别

1.struct中每一个成员会占用不同的内存,相互之间没有影响。

2.struct占用的内存大于等于所有成员占用的内存的总和//成员之间可能会存在缝隙

VS

1.union共用体的所有成员占用同一段内存,修改了一个成员会影响其他所有成员。

2.union共用体占用的内存等于最长的成员占用的内存。

3.union共用体使用了内存覆盖的技术,同一时刻只能保持一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。 

 union创建变量

//方法1-先定义共用体
union data{
    int n;
    char ch;
    short m;
};
union data a, b, c;
//方法2-定义共用体的同时创建变量
union data{
    int n;
    char ch;
    short m;
} a, b, c;
//其中-如果不在定义新的变量,也可以将共用体的名字省略。//共用体的名字
union {
    int n;
    char ch;
    double f;
} a,b,c;

 共用体 data 中,成员 f 占用的内存最多,为 8 个字节。

所以 data 类型的变量(也就是 a、b、c)也占用 8 个字节的内存


 一个特别好的一个例子

#include <stdio.h>
union data{
    int n;
    char ch;
    short m;
};
int main(){
    union data a;
    printf("%d, %d\n", sizeof(a), sizeof(union data) );
    a.n = 0x40;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.ch = '9';
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.m = 0x2059;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.n = 0x3E25AD54;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
   
    return 0;
}
运行结果:
4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54

这段代码不但验证了共用体的长度,还说明共用体成员之间会相互影响,修改一个成员的值会影响其他成员。

要想理解上面的输出结果,弄清成员之间究竟是如何相互影响的,就得了解各个成员在内存中的分布。以上面的 data 为例,各个成员在内存中的分布如下:

 成员 n、ch、m 在内存中“对齐”到一头,对 ch 赋值修改的是前一个字节,对 m 赋值修改的是前两个字节,对 n 赋值修改的是全部字节。也就是说,ch、m 会影响到 n 的一部分数据,而 n 会影响到 ch、m 的全部数据。

上图是在绝大多数 PC 机上的内存分布情况,如果是 51 单片机,情况就会有所不同:


共用体的应用

特别重要的一个例子

共用体在一般的编程中应用较少,在单片机中应用较多。对于 PC 机,经常使用到的一个实例是: 现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。请看下面的表格:

 f 和 m 分别表示女性和男性,s 表示学生,t 表示教师。可以看出,学生和教师所包含的数据是不同的。现在要求把这些信息放在同一个表格中,并设计程序输入人员信息然后输出。

如果把每个人的信息都看作一个结构体变量的话,那么教师和学生的前 4 个成员变量是一样的,第 5 个成员变量可能是 score 或者 course。当第 4 个成员变量的值是 s 的时候,第 5 个成员变量就是 score;当第 4 个成员变量的值是 t 的时候,第 5 个成员变量就是 course。

经过上面的分析,我们可以设计一个包含共用体的结构体,请看下面的代码:

#include <stdio.h>
#include <stdlib.h>
#define TOTAL 4  //人员总数
struct{
    char name[20];
    int num;
    char sex;
    char profession;
    union{
        float score;
        char course[20];
    } sc;
} bodys[TOTAL];
int main(){
    int i;
    //输入人员信息
    for(i=0; i<TOTAL; i++){
        printf("Input info: ");
        scanf("%s %d %c %c", bodys[i].name, &(bodys[i].num), &(bodys[i].sex), &(bodys[i].profession));
        if(bodys[i].profession == 's'){  //如果是学生
            scanf("%f", &bodys[i].sc.score);
        }else{  //如果是老师
            scanf("%s", bodys[i].sc.course);
        }
        fflush(stdin);
    }
    //输出人员信息
    printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n");
    for(i=0; i<TOTAL; i++){
        if(bodys[i].profession == 's'){  //如果是学生
            printf("%s\t%d\t%c\t%c\t\t%f\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.score);
        }else{  //如果是老师
            printf("%s\t%d\t%c\t%c\t\t%s\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.course);
        }
    }
    return 0;
}

运行结果:

Input info: HanXiaoXiao 501 f s 89.5↙
Input info: YanWeiMin 1011 m t math↙
Input info: LiuZhenTao 109 f t English↙
Input info: ZhaoFeiYan 982 m s 95.0↙

Name            Num     Sex     Profession      Score / Course
HanXiaoXiao     501     f       s               89.500000
YanWeiMin       1011    m       t               math
LiuZhenTao      109     f       t               English
ZhaoFeiYan      982     m       s               95.000000

转载整理:

1.C语言共用体(C语言union用法)详解 

<think>好的,用户现在问的是C语言共用体union)。之前他们问过结构体的嵌套访问,所以可能对结构体已经有了一定的了解。现在转向共用体,可能需要先明确共用体和结构体的区别,这是关键点。 用户可能是刚开始学习C语言,或者正在复习数据结构部分。他们可能知道结构体是多个成员同时存在的,而共用体则是共享内存空间的。需要解释清楚共用体的定义、内存分配方式以及使用场景。 要考虑到用户可能的疑问,比如共用体有什么用,什么时候该用它,有没有什么注意事项。比如,共用体可以节省内存,但同一时间只能使用一个成员,这可能带来数据覆盖的问题,需要提醒用户注意。 另外,用户之前的问题是关于如何访问嵌套结构体的成员,所以可能对如何访问共用体的成员也有疑问。但共用体的访问方式和结构体类似,都是使用点或箭头操作符,但要注意成员之间的覆盖问题。 可能需要举一些实际的例子,比如用共用体处理不同类型的数据,或者用来做类型转换。比如网络传输中处理不同数据包,或者硬件寄存器映射,这些实际应用场景能帮助用户理解。 还要注意语法细节,比如共用体的定义方式,和结构体的对比,初始化方法,以及如何正确访问成员。同时,常见错误比如同时使用多个成员导致的数据错误,需要强调避免。 最后,总结共用体的优缺点,适用场景,帮助用户决定在什么情况下使用共用体。可能还需要对比结构体和共用体的内存布局,加深理解。</think>好的!C语言中的**共用体union)**是一种特殊的数据结构,允许在**同一内存区域存储不同类型的数据**。下面通过具体示例和对比结构体,详细说明共用体的核心特性和使用方法: --- ### **一、共用体的定义** #### **基本语法** ```c union 共用体名 { 数据类型 成员1; 数据类型 成员2; // ... }; ``` **示例**: ```c union Data { int i; float f; char str[20]; }; ``` --- ### **二、共用体的核心特性** #### **1. 内存共享** - **所有成员共享同一块内存空间** - 结构体:各成员有独立内存空间,总大小=所有成员大小之和 - 共用体:总大小=最大成员的大小 **验证代码**: ```c struct S { int a; float b; }; // sizeof(struct S) = 4 + 4 = 8 union U { int a; float b; }; // sizeof(union U) = 4 (最大成员int/float的大小) ``` #### **2. 同一时间只能使用一个成员** - **修改一个成员会覆盖其他成员的值** **示例**: ```c union Data data; data.i = 10; // 此时内存存放整数10 data.f = 220.5; // 覆盖内存,整数10被浮点数220.5的二进制表示替代 strcpy(data.str, "hello"); // 再次覆盖内存 ``` --- ### **三、共用体的使用场景** #### **1. 节省内存** - 适用于多个数据类型**不会同时使用**的情况 **案例**:网络协议数据包解析 ```c union Packet { int raw; // 原始数据 struct { // 解析后的数据 unsigned char type; unsigned short length; } parsed; }; ``` #### **2. 类型转换** - 直接通过内存二进制转换数据类型 **示例**:将float按整数格式读取 ```c union Converter { float f; int i; } c; c.f = 3.14; printf("浮点数的二进制表示: %x", c.i); // 输出IEEE754格式的十六进制 ``` #### **3. 硬件寄存器映射** - 处理同一寄存器不同位域的解释 ```c union StatusReg { uint32_t value; struct { uint32_t error_flag : 1; uint32_t data_ready : 1; uint32_t reserved : 30; } bits; }; ``` --- ### **四、具体操作示例** #### **1. 声明与初始化** ```c union Data data; // 声明 union Data data = {.i = 100}; // C99标准初始化第一个成员 // union Data data = {100}; // 传统初始化方式 ``` #### **2. 成员访问** ```c data.i = 10; // 通过点运算符访问 printf("%d", data.i); union Data *p = &data; p->f = 3.14; // 通过指针使用箭头运算符 ``` --- ### **五、常见错误及解决方法** #### **错误1:误用未初始化的成员** ```c union Data data; data.i = 10; printf("%f", data.f); // 错误!此时内存被解释为int,按float读取会得到无意义值 ``` **解决方法**:始终明确当前正在使用的成员类型 #### **错误2:同时操作多个成员** ```c data.i = 10; data.f = 20.5; // 覆盖了i的值 strcpy(data.str, "test"); // 覆盖了整个内存区域 ``` **解决方法**:严格遵循**单成员使用原则** --- ### **六、与结构体的对比** | 特性 | 结构体 (struct) | 共用体 (union) | |---------------------|--------------------------|--------------------------| | **内存分配** | 成员内存独立 | 成员共享内存 | | **总大小** | 所有成员大小之和+对齐 | 最大成员大小 | | **成员使用** | 可同时存储和访问所有成员 | 同一时间只能使用一个成员 | | **典型用途** | 数据聚合 | 类型转换、节省内存 | --- ### **七、总结** 1. **核心价值**:通过内存共享实现灵活的数据存储,但需要严格管理成员使用顺序 2. **使用原则**: - 明确当前有效成员 - 避免未定义的成员访问 3. **适用场景**: - 需要节省内存且数据类型互斥 - 底层硬件操作或二进制数据处理 合理使用共用体可以显著提升程序的灵活性和内存效率,但不当使用会导致难以调试的数据错误!建议配合注释明确成员使用逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值