当前位置: 首页 > news >正文

C语言自定义数据类型详解(四)——联合体

好的,接下来我们来学习最后一个自定义数据类型——联合体。

一、什么是联合体:

联合体又叫共用体,用关键字union来进行定义。又因为所有的成员变量共用同一段内存空间(关于这一点,我们不久就会加以验证),所以它是一种比较特殊的自定义类型。

二、联合体的内存布局:

(1)验证联合体成员共用同一块空间:

我们前面已经提到了说联合体它的成员变量都是共用同一段内存空间的,我们可以通过下面这个代码对这一结论加以验证:

#include<stdio.h>
union Uo
{int a;char i;
};
int main()
{union Uo u;printf("sizeof(u) == %zd\n", sizeof(u));printf("%p\n", &(u.a));printf("%p\n", &(u.i));return 0;
}

运行效果:

 

我们发现对于联合体u,它的大小是4Byte,且无论是针对它的成员变量a取地址,还是针对它的成员变量i取地址,它的结果都是一样的

我们可以进一步做一些事情,我们修改变量a的值,然后来观察成员变量i是否会受影响。因此我们写出下面这个代码:

#include<stdio.h>
union Uo
{int a;char i;
};
int main()
{union Uo u;u.a = 0x44332211;//%x是以十六进制打印整数:printf("0x%x\n", u.a);printf("0x%x\n", u.i);return 0;
}

运行结果(注意这里的结果你可能和我不一样,因为这和机器是小端字节序,还是大端字节序有关系。而博主现在是小端字节序的机器):

 

我们发现对联合体中某一个成员变量的值进行修改,也会影响到其他的成员变量。这里又进一步佐证了联合体的成员变量共用同一段内存空间这一事实。

综上,对于联合体变量union Uo u来说,它的内存布局是:


(2)联合体内存大小的计算:

有很多小伙伴在联合体这里会犯一个错误,认为联合体的大小就是最大成员变量的大小。但是其实不然,就比如说下面这个代码场景:

#include<stdio.h>
union Uo
{int a;char i[5];
};
int main()
{union Uo u;printf("%zd\n", sizeof(u));return 0;
}

运行结果:

所以关于联合体的大小:我们认为联合体的大小至少是最大成员变量的大小。当最大成员变量的大小不是最大对齐数的整数倍时(关于对齐数可以看博主的前面的博客C语言自定义数据类型详解(二)——结构体类型(下)-CSDN博客)需要进行内存对齐

三、联合体的应用场景:

我们试想这么一个场景:我们要求设计一些数据类型来存储图书布袋衬衫这三个商品的一些属性。那首先分析这三个商品,它们都有各自以下这些属性:

图书:库存量,价格,书名,作者;

布袋:库存量,价格,样式;

衬衫:库存量,价格,颜色,尺寸;

那据此,你可不可以设计下面这样的:

struct book
{int _stock;  //库存float _price;//价格char _bookName[30];//书名char _writer[30];  //作者
};
struct bag
{int _stock;  //库存float _price;//价格char _style[30];//样式
};
struct shirt
{int _stock;  //库存float _price;//价格char color[15];//颜色size_t _size;  //尺寸
};

但是你有没有觉得这个设计比较冗余,因为库存量和价格都是这些商品共有的属性。这在C++,Java里面可以通过继承的方式来消除这种设计上的冗余,那C语言呢?OK,C语言可以借助联合体设计出下面这个结构体:

#include<stdio.h>
#include<string.h>
struct commodity
{int _stock;  //库存float _price;//价格//这里面都是匿名结构体和匿名联合体哦!union{struct{char _bookName[30];//书名char _writer[30];  //作者} _book;struct{char _style[30];//样式} _bag;struct{char color[15];//颜色size_t _size;  //尺寸} _shirt;}_item;
};
int main()
{struct commodity com;//注意这里的_writer是char* const的指针(常量指针),所以不能写作com._item._book._writer = "MoYan";strcpy(com._item._book._writer, "MoYan");printf("The writer of the book is %s\n", com._item._book._writer);return 0;
}

OK,这次的知识分享就到这里了,我们下次再见!

http://www.dtcms.com/a/301285.html

相关文章:

  • 欧拉图与欧拉回路
  • Windows---动态链接库Dynamic Link Library(.dll)
  • 裴蜀定理应用
  • Ubuntu Linux 如何配置虚拟内存 —— 一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录8
  • GRPO强化学习缓解多模态大模型OCR任务的幻觉思路及数据生成思路
  • 【Oracle】Oracle分区表“排雷“指南:当ORA-14400错误找上门时如何优雅应对
  • 【数据结构与算法】数据结构初阶:详解排序(二)——交换排序中的快速排序
  • 【Web安全】深入浅出理解“SQL注入-伪静态注入”及空格限制绕过技巧
  • linux 板卡实现vxi11服务
  • Qwen3安装使用教程:引领推理型大模型新时代
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-35,(知识点:三极管知识点,电路电压计算题,三极管电压计算,PNP三极管)
  • linux 部署 flink 1.15.1 并提交作业
  • 数据上新|最新省、地级市农业新质生产力2002-2025
  • Linux vimgrep 详解
  • 深度学习篇---优化器
  • 上位机知识篇---Tailwind CSS
  • Linux内核设计与实现 - 第15章 进程地址空间
  • python-列表推导式,迭代器和生成器,上下文管理器
  • Unity3D 平台宏定义
  • 双指针算法技巧
  • CCF-GESP 等级考试 2025年6月认证C++七级真题解析
  • PyQt5图形和特效(Qss的UI美化)
  • zabbix-agent静默安装
  • MinIO 用户管理与权限控制详解
  • LINUX727 磁盘管理回顾1;配置文件回顾
  • 数据类型处理流讲解
  • 《中国棒球》cba外援规则·棒球1号位
  • Java排序中(a).compareTo(b)与Integer.compare(a, b)区别
  • Java学习-------外观模式
  • incus套件在 主力 Linux Distros 上的安装配置与基本使用