深入明白 C 语言中的联合体

打印 上一主题 下一主题

主题 972|帖子 972|积分 2916

目录
弁言
一、 联合体的定义与基本用法
1.联合体的定义
2.基本用法
二、 联合体与结构体的区别
1.结构体
2.联合体
3.对比 
​编辑三、联合体的上风
1. 节流内存
2. 提高服从
3. 代码简洁性
四、联合体的存储细节
1.内存对齐
2.巨细计算
五、联合体的高级用法
1.匿名联合体
2.联合体数组
3.联合体进行类型转换
六、注意事项
总结

弁言

联合体(union)是 C 语言中的一种特别数据结构,答应在同一内存位置存储差别类型的数据。它与结构体(struct)雷同,但存在显著的差别。明白联合体的定义、基本用法、上风、存储细节及其高级用法,有助于在实际编程中有效地利用这一数据结构。
一、 联合体的定义与基本用法

1.联合体的定义

在 C 语言中,联合体通过 union 关键字定义。其基本语法格式如下:
  1. union 联合体名 {
  2.     数据类型1 成员名1;
  3.     数据类型2 成员名2;
  4.     ...
  5. };
复制代码
2.基本用法

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. union Data {
  4.         int i;
  5.         float f;
  6.         char str[20];
  7. };
  8. int main() {
  9.         union Data data;
  10.         data.i = 10;
  11.         printf("data.i = %d\n", data.i);
  12.         data.f = 220.5;
  13.         printf("data.f = %.1f\n", data.f);
  14.         snprintf(data.str, sizeof(data.str), "Hello, World!");
  15.         printf("data.str = %s\n", data.str);
  16.         return 0;
  17. }
复制代码
运行结果:

union Data 定义了一个联合体 Data,它可以存储 int、float 或 char 数组。
由于所有成员共享同一块内存,因此设置一个成员的值会覆盖其他成员的值。
二、 联合体与结构体的区别

   1.结构体

  

  • 内存分配:结构体中的每个成员都分配独立的内存地区,结构体的巨细是所有成员巨细之和(可能还会有添补字节)。
  • 数据存取:结构体的每个成员都可以独立地存取和修改。
  2.联合体

  

  • 内存分配:联合体中的所有成员共享同一块内存,联合体的巨细即是最大成员的巨细。
  • 数据存取:同一时间只能访问一个成员,修改一个成员会覆盖其他成员的数据。
  3.对比 

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. typedef struct {
  4.         char c;
  5.         int i;
  6. } MyStruct;
  7. typedef union {
  8.         char c;
  9.         int i;
  10. } MyUnion;
  11. int main() {
  12.         MyStruct s;
  13.         MyUnion u;
  14.         // 结构体
  15.         s.c = 'a';
  16.         s.i = 20;
  17.         printf("Struct:\n字符:%c, 数字:%d \n", s.c, s.i);
  18.         printf("Size of MyStruct:%d\n", sizeof(MyStruct));
  19.         // 联合体
  20.         u.c = 'a';
  21.         printf("Union: \n字符:%c,", u.c);
  22.         u.i = 20;
  23.         printf("数字:%d\n", u.i);
  24.         printf("Size of MyUnion:%d", sizeof(MyUnion));
  25.         return 0;
  26. }
复制代码
运行结果:

内存示意图;
三、联合体的上风


   1. 节流内存

  由于联合体的所有成员共享同一块内存,联合体通常比结构体节流内存。在需要存储多种差别类型但不会同时利用的数据时,联合体特别有用。
  2. 提高服从

  联合体答应在差别数据类型之间进行高效的转换。对于需要在差别数据格式之间切换的应用场景,联合体能够简化数据处置惩罚和转换过程。
  3. 代码简洁性

  利用联合体可以淘汰代码中对数据类型的重复处置惩罚,提高代码的简洁性和可维护性。
  四、联合体的存储细节

1.内存对齐

差别数据类型在内存中的对齐要求差别。联合体的内存对齐取决于最大成员的对齐要求。编译器可能会对联合体进行内存对齐,以提高访问服从。
2.巨细计算

      •联合的⼤⼩⾄少是最⼤成员的⼤⼩。       •当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时间,就要对⻬到最⼤对⻬数的整数倍。    示例:
  1. #include <stdio.h>
  2. union Un1
  3. {
  4.         char c[5];//共占5个字节
  5.         int i;//最大对齐数,占4字节
  6. };
  7. union Un2
  8. {
  9.         short c[7];//共占14个字节
  10.         int i;//最大对齐数,占4字节
  11. };
  12. int main()
  13. {
  14.         //下⾯输出的结果是什么?
  15.         printf("%d\n", sizeof(union Un1));
  16.         printf("%d\n", sizeof(union Un2));
  17.         return 0;
  18. }
复制代码
运行结果:

五、联合体的高级用法

1.匿名联合体

匿名联合体(Anonymous Union)是一种不需要命名的联合体。它的主要作用是简化代码,特别是在结构体中直接访问联合体成员时,可以省略联合体的名字。
假设我们有一个结构体,此中包罗一个匿名联合体用于存储差别的数据格式。
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. typedef struct {
  4.     int type;        // 数据类型标识符
  5.     union {
  6.         int i;
  7.         float f;
  8.         char str[20];
  9.     }; // 匿名联合体
  10. } DataPacket;
  11. int main() {
  12.     DataPacket packet;
  13.     // 设置为整数类型
  14.     packet.type = 1;
  15.     packet.i = 1234; // 直接访问联合体的成员
  16.     printf("Packet Type: %d, Integer Value: %d\n", packet.type, packet.i);
  17.     // 设置为浮点类型
  18.     packet.type = 2;
  19.     packet.f = 56.78;
  20.     printf("Packet Type: %d, Float Value: %.2f\n", packet.type, packet.f);
  21.     // 设置为字符串类型
  22.     packet.type = 3;
  23.     snprintf(packet.str, sizeof(packet.str), "Hello!");
  24.     printf("Packet Type: %d, String Value: %s\n", packet.type, packet.str);
  25.     return 0;
  26. }
复制代码
在 DataPacket 结构体中,union 定义为匿名联合体,因此可以直接访问其成员(如 i、f 和 str),而无需利用联合体名。
2.联合体数组

联合体数组用于存储多个联合体实例。每个联合体实例可以存储差别类型的数据,并且每个联合体实例共享雷同的内存布局。
假设我们需要处置惩罚多个数据包,每个数据包可以包罗差别类型的数据。我们可以利用联合体数组来管理这些数据包。
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. typedef union {
  4.     int i;
  5.     float f;
  6.     char str[20];
  7. } DataUnion;
  8. int main() {
  9.     DataUnion dataArray[3];
  10.     // 设置数组元素为整数
  11.     dataArray[0].i = 42;
  12.     // 设置数组元素为浮点数
  13.     dataArray[1].f = 3.14;
  14.     // 设置数组元素为字符串
  15.     snprintf(dataArray[2].str, sizeof(dataArray[2].str), "Union Array");
  16.     // 打印数组元素
  17.     printf("dataArray[0] (int): %d\n", dataArray[0].i);
  18.     printf("dataArray[1] (float): %.2f\n", dataArray[1].f);
  19.     printf("dataArray[2] (str): %s\n", dataArray[2].str);
  20.     return 0;
  21. }
复制代码
DataUnion:定义了一个联合体,可以存储整数、浮点数或字符串。
dataArray[3]:创建了一个联合体数组 dataArray,包罗 3 个 DataUnion 实例,每个实例可以存储差别的数据类型。
访问数组元素时,每个元素的内容可以根据需要进行设置和读取。 
3.联合体进行类型转换

联合体可以用作差别数据类型之间的转换工具。特别是,当需要将雷同内存中的数据以差别格式进行解释时,联合体可以提供一种有效的方法。
假设我们有一个float数值,需要以int类型访问其位模式。这可以通过联合体进行实现。
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. typedef union {
  5.     float f;
  6.     uint32_t i;
  7. } FloatIntUnion;
  8. int main() {
  9.     FloatIntUnion data;
  10.     data.f = 3.14159; // 设置浮点数
  11.     // 打印浮点数及其对应的整数位模式
  12.     printf("Float value: %.5f\n", data.f);
  13.     printf("Integer value: 0x%08X\n", data.i);
  14.     return 0;
  15. }
复制代码
FloatIntUnion:联合体定义,此中一个成员是 float 类型,另一个成员是 uint32_t 类型。uint32_t 用于表示浮点数的位模式。
通过 data.f 设置浮点数,然后可以通过 data.i 访问该浮点数的内存位模式。这种方法用于调试、解析数据格式或其他低级操作。
六、注意事项

   利用联合体时,应注意以下几点:
  成员访问:确保在访问联合体的成员时,访问的是最近一次赋值的成员。
内存重叠:联合体成员之间的内存重叠可能导致数据损坏,因此利用时要格外小心。
  总结

通过以上内容,我们深入了解了C语言中的联合体。合理利用联合体可以提高代码的机动性和服从,但同时也需要谨慎处置惩罚可能出现的内存重叠和数据类型转换题目。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表