共用体和结构体

本文对比了C语言中结构体和共用体的数据存储方式、内存布局以及成员独立性,通过实例说明了它们在内存使用和成员访问上的关键区别,以及在实际项目中的应用场景,如员工信息系统和数据解析。
摘要由CSDN通过智能技术生成

共用体(Union)和结构体(Struct)都是C语言中用于定义复合数据类型的关键工具,但它们在数据存储和管理内存的方式上有重要区别。

结构体(Struct)

  • 内存布局:在结构体中,每个成员都有自己的内存空间,结构体的总大小至少是所有成员大小的总和(可能更大,因为内存对齐)。
  • 成员访问:结构体的每个成员可以同时拥有各自的值。更改一个成员的值不会影响其他成员。
  • 用途:结构体通常用于将相关的数据项组合在一起,例如表示一个对象的不同属性。
struct Person {
    char name[50];
    int age;
    float height;
};

共用体(Union)

  • 内存布局:共用体中的所有成员共享同一块内存空间,共用体的大小等于其最大成员的大小。
  • 成员访问:一次只能有效地使用共用体的一个成员。赋值给某个成员会覆盖其他成员的值,因为它们共享内存。
  • 用途:共用体常用于存储可能以多种形式存在的数据,或用于节省内存,尤其是当不同的成员不会同时使用时。
union Data {
    int i;
    float f;
    char str[20];
};

关键区别

  • 内存使用:结构体为每个成员分配单独的内存,而共用体使所有成员共享内存。

  • 成员独立性:结构体的成员是独立的,共用体的成员则不是。

  • 大小:结构体的大小至少等于其所有成员大小之和,共用体的大小等于其最大成员的大小。

结构体举例:员工信息系统

假设开发者在创建一个员工信息系统。在这个系统中,每个员工有姓名、年龄和工号等属性。这些属性可以使用结构体来表示,因为每个员工的这些信息都是相互独立且同时存在的。

#include <stdio.h>

// 定义员工结构体
struct Employee {
    char name[50];
    int age;
    int employeeId;
};

int main() {
    // 创建一个Employee结构体变量
    struct Employee emp1;

    // 设置emp1的信息
    strcpy(emp1.name, "Alice");
    emp1.age = 30;
    emp1.employeeId = 1001;

    // 打印emp1的信息
    printf("Employee Name: %s\n", emp1.name);
    printf("Age: %d\n", emp1.age);
    printf("Employee ID: %d\n", emp1.employeeId);

    return 0;
}

共用体举例:数据解析

假设你正在编写一个程序来解析不同类型的数据包。每个数据包的第一个字节是一个类型标识符,它决定了包的剩余部分应该如何解释。这种情况下,可以使用共用体,因为数据包的不同部分(虽然都存在),但在任何给定时间只使用其中的一个。

#include <stdio.h>

// 定义数据包共用体
union DataPacket {
    int intValue;
    float floatValue;
    char strValue[20];
};

int main() {
    // 创建一个DataPacket共用体变量
    union DataPacket packet;

    // 假设我们接收了一个整数数据
    packet.intValue = 123;

    // 由于我们知道当前数据类型是整数,只打印intValue
    printf("Integer Value: %d\n", packet.intValue);

    // 之后,假设我们接收了一个字符串数据
    strcpy(packet.strValue, "Hello World");

    // 现在只使用strValue
    printf("String Value: %s\n", packet.strValue);

    // 注意,此时intValue的内容已经被覆盖

    return 0;
}

注意,此时intValue的内容已经被覆盖

在共用体(Union)中,所有成员共享同一块内存区域。这意味着当你更改共用体中的一个成员时,其他成员所占用的内存内容也会被更改。在上面的例子中,这个特性体现在对共用体 DataPacket 成员的赋值操作上。
首先,给 intValue 成员赋值:

packet.intValue = 123;

然后,给 strValue 成员赋值:

strcpy(packet.strValue, "Hello World");

在这个赋值操作中,共用体 packet 的内存被用来存储字符串 “Hello World”。由于 strValue 和 intValue 共享相同的内存区域,原先存储的整数 123 的二进制表示被 “Hello World” 的内容覆盖了。
当你再次尝试访问 packet.intValue 时,得到的不再是原先存储的整数 123,而是内存中当前存储的 “Hello World” 字符串对应部分的二进制数据,解释为整数的形式。这通常会是一个无意义的数值,因为字符串的二进制表示与整数的二进制表示完全不同。
所以注意,此时intValue 的内容已经被覆盖是指:当 strValue 被赋予新值时,之前存储在 intValue 中的数据被新数据覆盖了。这正是共用体的核心特性,即所有成员共享同一块内存,因此任何时候只能安全地使用其中一个成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI1.0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值