数据结构 -- 共用体Union

news2024/11/19 19:29:22

在数据结构 -- 结构体Struct一文中详细介绍了结构体的定义以及内存对齐。在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体Union),也称为联合体。它的定义格式为:

union 共用体名{
    成员列表
};

1. 定义共用体变量

和结构体一样,共用体也是一种自定义的数据类型,是创建变量的模板,不占用内存空间。共用体变量才包含了实实在在的数据,需要内存空间来存储。共用体可以通过下面两种方式来定义:

  • 方式一:先定义共用体,再定义共用体变量

//定义data共用体
union data{
    int n;
    char ch;
    double f;
};

//定义两个共用体变量
union data a, b;

data为共用体名,里面包含n、ch、f这3个成员。ab则为两个data类型的共用体变量。

  • 方式二:在定义共用体的同时定义共用体变量

union data{
    int n;
    char ch;
    double f;
} a, b;

直接将变量放在共用体的最后即可。

如果只需要 a、b两个变量,后面不需要再使用共用体名定义其他变量,那么在定义时也可以省略共用体名。

2. 成员的获取和赋值

共用体使用了内存覆盖机制,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。所以共用体不能整体赋值,只能使用点号.获取单个成员,然后再进行赋值操作。

//注:下面每一次赋值后,n、ch、f三个变量的值均会改变
a.n = 40;
a.ch = '9';
a.f = 135;

3. 共用体的内存分配

共用体变量占用的内存大小等于最长的成员占用的内存大小,各成员都会从offset为0处开始存放,修改其中一个成员会影响其余所有成员。来看下面的实例:

//定义一个data共用体
union data{
    int n;
    char ch;
    short m;
};

int main(){
     
    //创建一个共用体变量a
    union data a;
    printf("a.size = %d, data.size = %d\n", sizeof(a), sizeof(union data) );
    //对成员a赋值
    a.n = 0x40;
    printf("n = %#X, ch = %c, m = %#hX\n",  a.n, a.ch, a.m);
    //对成员b赋值
    a.ch = '9';
    printf("n = %#X, ch = %c, m = %#hX\n", a.n, a.ch, a.m);
    //对成员c赋值
    a.m = 0x2059;
    printf("n = %#X, ch = %c, m = %#hX\n", a.n, a.ch, a.m);
   //再对成员a赋值
    a.n = 0x3E25AD54;
    printf("n = %#X, ch = %c, m = %#hX\n", a.n, a.ch, a.m);
   
    return 0;
}

在上面代码中创建了一个共用体变量a,里面有n、ch、m这三种不同数据类型的成员,分别对齐赋值,打印每一次赋值后的三个成员。

%X:表示将int类型数据以大写字母的形式输出十六位进制数。
%c:表示输出字符。
%hX:表示将short类型数据以大写字母的形式输出十六位进制数。
#:表示输出时加上前缀,用于区分不同进制的数字。比如:0x16,不加#时输出为16,加上输出为0x16。

打印结果为:

a.size = 4, data.size = 4
n = 0X40, ch = @, m = 0X40
n = 0X39, ch = 9, m = 0X39
n = 0X2059, ch = Y, m = 0X2059
n = 0X3e25ad54, ch = T, m = 0XAD54

从打印结果可知,共用体a的内存等于其最长成员int n所占的内存大小,为4字节。每次修改共用体中的某个成员,都会影响到其他成员的值。

4. 分析共用体的内存分配

共用体的每个成员都从其内存offset为0的地方存放,根据成员数据类型各占用对应字节大小的内存,每次为成员赋值时,都会覆盖修改所占内存,因此,其他成员的值也跟着变动了。以上面的共存体变量a为例,分别对其成员赋值,内存空间的变化情况就如下图所示:

 

图1 → 图2 → 图3 → 图4 → 图5

图1:表示共用体a及其成员的内存分配情况:

  • 每一格代表一个字节,从上到下表示地址由低到高分布。
  • a总共4字节,成员n、m、ch均从offset为0的地方开始存放,分别占用4字节、2字节、1字节的内存大小,内存存在重合部分。

图2:表示当赋值a.n = 0x40后,共用体a的内存空间变化:

1byte = 8bit,所以1个字节最大值为255,换算成十六进制为0xFF,而0x40小于0xFF,所以只需一个字节保存。存储系统的分布方式大多采用小端模式,即在内存的第一个字节里保存0x40,此时成员n、ch、m的值均为0x40。

存储系统分布方式,以0x12345678为例:
1.大端模式:高位在低地址,低位在高地址。即12在低地址,78在高地址。
2.小端模式:高位在高地址,低位在低地址。即12在高地址,78在低地址。

因此,当赋值a.n = 0x40后,打印结果为:n = 0X40, ch = @, m = 0X40。(0x40对应的字符为@

图3:表示当赋值a.ch = '9'后,共用体a的内存空间变化:

字符9的十六进制ASCII码值为0x39,在赋值后,内存里第一个字节的0x40被覆盖,变为0x39。

因此当赋值a.ch = '9'后,打印结果为:n = 0X39, ch = 9, m = 0X39。

图4:表示当赋值a.m = 0x2059后,共用体a的内存空间变化:

由于0x2059小于0xFFFF,所以需要两个字节来保存,在赋值后,内存里第一个字节里的39被覆盖,前两个字节分别保存0x59、0x20。

因此当赋值a.m = 0x2059后,ch为0x59,对应字符Y,所以打印结果为:n = 0X2059, ch = Y, m = 0X2059。

图5:表示当赋值a.n = 0x3E25AD54后,共用体a的内存空间变化:

由于0x3E25AD54小于0xFFFFFFFF,所以需要4字节来保存。在赋值后,内存的4个字节分别保存54、AD、25、3E。

因此当赋值a.n = 0x3E25AD54后,ch为0x54,对应字符T,m为0xAD54,所以打印结果为:n = 0X3E25AD54, ch = T, m = 0XAD54。

5. 共用体和结构体的区别

  • 结构体的第一个成员会从offset为0的地方开始存放,其它成员按顺序存储,各成员会占用不同的内存,互相之间没有影响;
    共用体的所有成员都会从offset为0的地方存放,各成员内存会存在重,修改一个成员会影响其余所有成员。

  • 结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙)。
    共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。



作者:东篱采桑人
链接:https://www.jianshu.com/p/600ef075c984
来源:简书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/502509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CVPR红外小目标检测】红外小目标检测中的非对称上下文调制(ACM)

论文题目: Asymmetric Contextual Modulation for Infrared Small Target Detection 红外小目标检测中的非对称上下文调制 红外小目标数据集 目标个数分布:约90%图片中只有一个目标,约10%图片有多个目标(在稀疏/显著的方法中&am…

网文助手。

网文助手 简述 网文助手,免费高质量小说资料网站,支持笔记本和手机端,主要有以下功能。 随机生成小说男女姓名,和尊称随机生成地域和势力名称随机生成功法秘籍、招式战技、法宝兵器、丹药和阵法随机生成妖兽、凶地、天材地宝随…

Prometheus监控报警+Grafana loki日志聚合系统

Prometheus监控报警Grafana loki日志聚合系统 参考文档 https://blog.csdn.net/m0_57480266/article/details/121190725?spm1001.2101.3001.6650.1&utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-121190725-blog-111992382.235%5Ev3…

二十一、线索转换3:线索的备注转化为客户联系人的备注

功能需求 3.线索的备注信息--》客户备注 4.线索的备注---》联系人备注 5.线索市场活动关系---》联系人市场活动关系 流程图 代码实现&#xff1a;线索的备注转化为客户联系人的备注 1.clueRemarkMapper /*** 根据线索id 查询备注2*/List<ClueRemark> selectInitialC…

Windows本地MySQL升级

一、删除原来的MySQL 删除 C:\Programs Files、C:\Programs Files(x86)、C:\ProgramData 中的所有MySQL目录 找到MySQL数据库中的data保存到其他位置&#xff0c;升级后可以恢复数据库数据 【备份数据】 删除注册表中MySQL的信息 计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet…

Py01·环境搭建

Python环境搭建 官网下载python3.7.3&#xff1a;https://www.python.org/downloads/release/python-373/ 配置系统环境变量目录&#xff1a; E:\ldtools\python3.7.3\python.exe E:\ldtools\python3.7.3\Scripts\pip.exe python.exe 运行环境 pip.exe 包管理器 安装mysql环…

TypeScript 最近各版本主要特性总结

&#xff08;在人生的道路上&#xff0c;当你的期望一个个落空的时候&#xff0c;你也要坚定&#xff0c;要沉着。——朗费罗&#xff09; TypeScript 官网 在线运行TypeScript代码 第三方中文博客 特性 typescript是javascript的超集&#xff0c;向javascript继承额外的编辑…

K8s之Namespace名称空间详解

文章目录 一、名称空间概念二、名称空间基本操作1、创建Namespace的两种方式2、Namespace资源限额 一、名称空间概念 K8s中文手册&#xff1a; K8s名称空间中文官方手册&#xff1a; Kubernetes 支持多个虚拟集群&#xff0c;它们底层依赖于同一个物理集群。 这些虚拟集群被…

UUID使用

1.UUID是什么&#xff1f; UUID 是指&#xff08;Universally Unique Identifier&#xff09;通用唯一识别码&#xff0c;128位。RFC 4122描述了具体的规范实现。 2.UUID解决问题&#xff1f; 分库分表后自增Id重复问题。 3.UUID作用&#xff1f; UUID 的目的是让分布式系…

[数据库系统] 一、创建表以及使用主键约束(educoder)

1.任务&#xff1a;在数据库中创建一个表。 2.需要掌握&#xff1a; 如何在指定数据库中创建表。 知识点&#xff1a;如何在指定数据库中创建表。 我们先来了解一下在数据库中创建表的规则&#xff1a; CREATE TABLE 表名(字段名,数据类型,字段名,数据类型,.....) 例如&…

Oracle 体系结构

文章目录 Oracle体系结构Oracle的内存结构Oracle的进程结构服务器进程后台进程可选后台进程 物理存储结构逻辑存储结构 概念&#xff1a; Oracle server由Oracle instance和Oracle database组成&#xff0c;Oracle instance由后台进程和共享内存组成&#xff0c;Oracle的实例包…

《走进对象村4》之面向对象的第一大特性——封装

文章目录 &#x1f680;文章导读1、封装的概念2、访问限定修饰符3、如何进行封装4、封装的优点&#xff1a; &#x1f680;文章导读 在本篇文章中&#xff0c;将详细的对封装进行总结&#xff0c;文章仅仅是个人的一些理解&#xff0c;如果有错误的地方&#xff0c;还望指出看完…

八岁都能懂:O(N)条件下在N个元素中找出第K小的元素

目录 1 进入情境1-1 金字塔道具1-2 感觉还不够1-3 万能筛子1-4 怎么用呢 2 代码实现2-1 伪代码描述2-2 完整实例c 3 引申3-1 完美的折半舍弃3-2 找出前K小的元素(topK方法&#xff09;3-3 O(n)效率下求中位数参考资料 1 进入情境 生日&#xff0c;朋友送了一堆弹珠&#xff0c;…

[PyTorch][chapter31][卷积]

前言&#xff1a; 卷积神经网络 是 计算机视觉里面应用非常广泛的一个模型。 卷积神经网络 成功案例 人脸识别,指纹识别等应用. 卷积的本质是图像的特征提取&#xff0c; 在冈萨雷士版本《数字图像处理》处理有专门的章节讲解 各种卷积核&#xff0c;在通讯原理里面&#xff0…

MOD09A1、MYD09A1 文件说明

总体介绍 文件全称为 MODIS Terra/Aqua Surface Reflectance 8-Day L3 Global 500 m。文件名称的示例为 “MOD09A1.A2000337.h11v05.005.2006342055602.hdf”。下载下来的 hdf 包括 13 个子数据集&#xff0c;一个 tile 包括 2400*2400 个像元。各数据集的性质如下表所示。 Sci…

51单片机基础实验1

一.51单片机 51单片机&#xff0c;也称为AT89C51&#xff0c;是一种基于Intel 8051架构的8位单片机。它是广泛应用于嵌入式系统和微控制器领域的常见芯片之一。其具有高度灵活性、可编程性和可靠性&#xff0c;因此被广泛应用于各种应用场景中。 51单片机的主要特点包括&…

三十、组播技术——IGMP、IGMP-snooping、PIM-DM、PIM-SM

文章目录 组播概述1、IP组播通信概念2、组播和单播ip地址3、组播MAC4、组播应用场景5、PIM、IGMP、IGMP-snooping 一、IGMP 协议二、PIM DM&#xff08;密集模式&#xff09;1、配置示例如下&#xff1a;2、PIM DM的局限性 三、PM SM&#xff08;稀疏模式&#xff09; 组播概述…

【python学习】基础篇-文件与系统-os 模块及 os.path 相对路径与绝对路径

在 Python 中&#xff0c;内置了os 模块及其子模块 ospath&#xff0c;用于对目录或文件进行操作。 在使用 os 模块或者 os.path 模块时&#xff0c;应首先使用 import 语句将其导入&#xff0c;然后才可以使用它们提供的函数或方法。 1、常用操作目录函数 2.相对路径与绝对路…

如何手写一个支持H.265的高清播放器

概述 音视频编解码技术在当前的互联网行业中十分热门&#xff0c;特别是高清视频播放器的开发&#xff0c;其中包括4K、8K等超高清分辨率的播放器&#xff0c;具有极高的市场需求和广泛的应用场景。H265编码技术更是实现高清视频压缩的重要手段之一。如果想要掌握音视频编解码…

微服务部署:蓝绿发布、滚动发布、灰度发布、金丝雀发布

前言 在项目迭代的过程中&#xff0c;不可避免需要上线。上线对应着部署&#xff0c;或者重新部署&#xff1b;部署对应着修改,修改则意味着风险。 1.蓝绿发布(Blue/Green Deployment) ①定义 蓝绿部署是不停老版本&#xff0c;部署新版本然后进行测试。确认OK后将流量切到新…