C++联合体详解!

个人主页:PingdiGuo_guo

收录专栏:C++干货专栏

大家伙新年快乐,今天我们来了解一下C++联合体。

文章目录

1.联合体

1.1联合体的概念

1.2联合体的思想

1.3联合体的作用

1.3.1内存优化

1.3.2二进制数据操作

1.3.3类型转换

1.3.4解决特定问题

1.4联合体的操作

1.4.1定义联合体

1.4.2初始化联合体

1.4.3赋值操作

1.4.4访问联合体成员

1.4.5注意事项

1.5联合体的分类

1.5.1 匿名联合体(Anonymous Union)

1.5.2 命名联合体(Named Union)

1.5.3 嵌套联合体(Nested Union)

1.6联合体和结构体的区别

1.6.1 相同之处  

1.6.2 区别

1.7联合体的练习

1.7.1 题目

1.7.2 解题步骤

1.7.3 代码示例

         1.8总结


1.联合体

1.1联合体的概念

联合体是一种特殊的用户自定义数据类型,在C++中,通过`union`关键字来定义。它由多个成员组成,但所有成员共享同一段内存空间。联合体的大小等于其内部最大的成员所占的内存大小。

1.2联合体的思想

联合体的设计思想在于高效地利用内存,特别是在需要在不同时间点以不同类型的值来解释同一块内存的情况下。联合体确保了同一内存区域可被看作是多种数据类型的任何一种,但在任何时刻只有一个成员的数据是有意义的。

1.3联合体的作用

1.3.1内存优化

当不同的数据类型在某一时间段内互斥使用同一内存空间时,联合体可以避免不必要的内存开销。


1.3.2二进制数据操作

在处理底层数据,如网络通信协议、文件格式解析等领域,联合体常用于根据不同上下文对同一内存区域的不同解读。


1.3.3类型转换

在一些场景下,联合体可以作为一种简便的类型转换手段,尤其是从一种数据类型到另一种数据类型直接“重映射”内存内容。


1.3.4解决特定问题

在某些特定的应用场景中,联合体可以帮助程序员实现特定的需求,比如在有限的硬件资源条件下,或者在设计特定算法时需要灵活改变数据视图。

需要注意的是,使用联合体时应当谨慎,因为没有机制保证同时访问不同类型的成员是安全的,因此通常要求开发者自行管理联合体内存的正确使用。此外,C++11标准引入了std::variant,它是联合体的一种更安全的替代品,它可以持有多种类型并跟踪当前存储的有效类型。

1.4联合体的操作

1.4.1定义联合体
 

// 定义一个联合体,包含整型、浮点型和字符型成员
union MyUnion {
int integerValue;
float floatValue;
char characterValue;
};

在这个例子中,MyUnion是一个联合体,它有三个成员:一个整数、一个浮点数和一个字符。这三个成员共享相同的内存空间。

1.4.2初始化联合体
 

// 初始化联合体
MyUnion myU;
// 或者直接初始化某个成员
MyUnion myUInit = { .integerValue = 100 }; // C++11开始支持指定初始化标签



这里,myU创建了一个未初始化的联合体实例。而myUInit则直接初始化了integerValue为100。

1.4.3赋值操作
 

// 赋值操作,只能对当前活动成员赋值
myUInit.integerValue = 42; // 正确,现在联合体中保存的是整数值42

// 尝试对非活动成员赋值(此时活动成员为integerValue)
myUInit.floatValue = 3.14f; // 实际上可能会覆盖掉integerValue的值

// 更改活动成员
myUInit.characterValue = 'A'; // 现在联合体中保存的是字符'A',之前保存的整数值已丢失



由于联合体在同一时间只有一个活跃成员,所以对非活跃成员的赋值会覆盖当前活跃成员的数据,而且编译器不会发出警告或错误。


1.4.4访问联合体成员
 

// 访问联合体成员
int intValue = myUInit.integerValue; // 取回最后一次赋值给integerValue的值
char charValue = myUInit.characterValue; // 取回最后一次赋值给characterValue的值



访问联合体成员时,应确保了解当前哪个成员是活跃的,否则获取的数据可能是无意义的。


1.4.5注意事项

- 在实际使用联合体时,需要清楚知道当前活跃成员是什么,以免发生未预期的数据覆盖。
- 联合体本身不提供机制追踪当前活跃成员,这需要程序员自己管理和记录。在C++17中引入了std::variant作为更安全的替代方案,它能保持类型安全并跟踪当前存储的有效类型。

1.5联合体的分类

1.5.1 匿名联合体(Anonymous Union)

匿名联合体没有名称,只能定义在一个结构体或类的内部,并且可以与该结构体或类的其他成员共享相同的命名空间。

示例代码:

struct MyStruct {
   int type;
   union {
      int intValue;
      float floatValue;
   };
};

int main() {
   MyStruct myVar;
   myVar.type = 0;
   myVar.intValue = 10;
   printf("%d\n", myVar.intValue);
   myVar.type = 1;
   myVar.floatValue = 3.14;
   printf("%.2f\n", myVar.floatValue);
   return 0;
}

1.5.2 命名联合体(Named Union)

命名联合体有一个特定的名称,可以在全局作用域或局部作用域中定义,并可以作为其他结构体,类等的成员。

示例代码:

     
 

union MyUnion {
   int intValue;
   float floatValue;
};

int main() {
   MyUnion myVar;
   myVar.intValue = 10;
   printf("%d\n", myVar.intValue);
   myVar.floatValue = 3.14;
   printf("%.2f\n", myVar.floatValue);
   return 0;
}

1.5.3 嵌套联合体(Nested Union)


嵌套联合体是指一个联合体的成员也可以是另一个联合体。

示例代码:
 

union Union1 {
   int intValue;
   float floatValue;
};

union Union2 {
   int intValue;
   Union1 nestedUnion;
};

int main() {
   Union2 myVar;
   myVar.nestedUnion.intValue = 10;
   printf("%d\n", myVar.nestedUnion.intValue);
   myVar.nestedUnion.floatValue = 3.14;
   printf("%.2f\n", myVar.nestedUnion.floatValue);
   return 0;
}

1.6联合体和结构体的区别

联合体(Union)与结构体(Struct)在C++中都是复合数据类型,它们都可以容纳多个不同类型的成员变量,但在内存布局和使用方式上有显著区别:

1.6.1 相同之处  


1. 定义:两者都通过关键字定义,并且都能包含不同类型的成员变量。
2. 命名:都可以通过`.`运算符或者指向它们的指针的`->`运算符来访问成员变量。


1.6.2 区别


1. 内存布局


- 结构体:结构体的每个成员变量在内存中都有自己的独立空间,按照声明顺序依次排列。
- 联合体:联合体的所有成员变量共享同一片内存区域,同一时刻只能存放一个成员变量的值,改变一个成员变量会影响到其他成员变量的值,因为它们都在同一个内存位置上。

2. 使用


- 结构体:允许同时存储所有成员变量的值,每个成员变量的值都是独立存在的。
- 联合体:在同一时间只能有一个成员有效,也就是说,虽然可以声明多个类型的成员,但只能激活其中的一个用于存储数据。

3. 大小


- 结构体的大小至少是其所有成员变量大小之和(可能还要加上对齐导致的额外空间)。
- 联合体的大小等于其所有成员中最大的成员的大小,因为它只分配足够的空间来容纳最大成员。

4. 应用场景


- 结构体常用于打包相关数据到一起,创建一个新的数据类型,适用于需要同时维护多个状态的情况。
- 联合体常用于节省内存空间,尤其是在需要根据上下文临时存储不同类型数据而又不需要同时保存多种数据的情况下,例如在网络编程中转换不同类型的协议数据包。

总结来说,结构体是为数据聚合和分离提供便利,而联合体则是为了在有限的空间内存储不同类型的单个数据。

1.7联合体的练习

1.7.1 题目


编写一个程序,定义一个联合体类型,它可以存储一个整数值或一个浮点数值。然后编写函数分别读取用户输入的整数和浮点数,并通过联合体打印出两种不同的表示方式。最后,设计程序逻辑以确保在同一时间只有一个类型的值被正确存储和显示。

1.7.2 解题步骤

1. 定义一个联合体类型,包含整数(int)和浮点数(float)两个成员变量。
2. 编写一个函数,接收用户输入的整数,将其存入联合体,并打印整数值。
3. 编写另一个函数,接收用户输入的浮点数,将其存入联合体,并打印浮点数值。
4. 在主函数中,先读取整数并打印,然后读取浮点数并打印,注意每次存入新值时旧值会被覆盖。



1.7.3 代码示例

#include <iostream>

// 定义联合体
union Number {
int intValue;
float floatValue;
};

// 函数:读取整数并打印
void readAndPrintInt(Number &num) {
std::cout << "Enter an integer value: ";
std::cin >> num.intValue;
std::cout << "The integer value is: " << num.intValue << std::endl;
}

// 函数:读取浮点数并打印
void readAndPrintFloat(Number &num) {
std::cout << "Enter a floating-point value: ";
std::cin >> num.floatValue;
std::cout << "The floating-point value is: " << num.floatValue << std::endl;
}

int main() {
Number myNumber;

// 先读取并打印整数
readAndPrintInt(myNumber);

// 现在读取并打印浮点数
// 注意:由于联合体内存区域共用,此处会覆盖之前存储的整数值
readAndPrintFloat(myNumber);

return 0;
}



大家请注意,尽管上述代码展示了如何使用联合体,但在实际应用中,直接读取不同类型的值并期望联合体能正确处理可能会有未定义行为的风险,特别是在没有显式地清除旧值的情况下。这是因为联合体不会自动跟踪当前生效的成员类型,因此从非活跃成员读取可能导致未定义的行为。在实际编程中,通常会配合额外的信息(如枚举或其他标记)来确定联合体当前存储的是哪种类型的值。

1.8总结

本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,谢谢大家啦!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

黄金交易策略(Nerve Nnife.mql4):趋势做单

完整EA&#xff1a;Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客 当大小趋势相同行情走向也相同&#xff0c;就会开仓做顺势单&#xff0c;并会顺势追单&#xff0c;以达到快速止盈平仓的效果。大趋势追求稳定&#xff0c;小趋势追求敏捷&#xff0c;行情走向比小趋势更敏…

【Java程序设计】【C00260】基于Springboot的企业客户信息反馈平台(有论文)

基于Springboot的企业客户信息反馈平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的企业客户信息反馈平台 本系统分为平台功能模块、管理员功能模块以及客户功能模块。 平台功能模块&#xff1a;在平台首页可…

【北邮鲁鹏老师计算机视觉课程笔记】06 corner 局部特征

【北邮鲁鹏老师计算机视觉课程笔记】06 corner 局部特征 1 局部特征的任务牵引&#xff1a;全景拼接 ①提取特征 ②匹配特征 ③拼接图像 我们希望特征有什么特性&#xff1f; ①可重复性 ②显著性 ③计算效率和表达紧凑性 ④局部性 2 特征点检测的任务 3 角点 在角点&#…

论文阅读:《Deep Learning-Based Human Pose Estimation: A Survey》——Part 1:2D HPE

目录 人体姿态识别概述 论文框架 HPE分类 人体建模模型 二维单人姿态估计 回归方法 目前发展 优化 基于热图的方法 基于CNN的几个网络 利用身体结构信息提供构建HPE网络 视频序列中的人体姿态估计 2D多人姿态识别 方法 自上而下 自下而上 2D HPE 总结 数据集…

npm ERR! network This is a problem related to network connectivity.

遇到 ETIMEDOUT 错误时&#xff0c;这表明npm尝试连接到npm仓库时超时了&#xff0c;这通常是由网络连接问题引起的。这可能是因为网络不稳定、连接速度慢、或者你的网络配置阻止了对npm仓库的访问。以下是一些解决这个问题的步骤&#xff1a; 1. 检查网络连接 首先&#xff…

Solidworks:从2D走向3D

Sokidworks 的强大之处在于三维实体建模&#xff0c;这个形状看似复杂&#xff0c;实际上只需要拉伸一次&#xff0c;再做一次减法拉伸就行了。第一次做三维模型&#xff0c;费了不少时间才搞明白。 接下来做一个稍微复杂一点的模型&#xff0c;和上面这个操作差不多&#xff0…

华为配置双链路热备份场景下的无线配置同步示例

配置双链路热备份场景下的无线配置同步示例 组网图形 图1 配置双链路热备份示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 某企业为保证业务的正常运营&#xff0c;希望提高网络可靠性&#xff0c;同时还希望减少配置维护的工作量。为满…

团队配置管理规范浅见

在一段时间的工作过程中配置管理工作确实对我们的生产活动产生了巨大的工作量&#xff0c;现在就这个工作来进行梳理一下。 本文主要分为两部分&#xff1a; 1、借用软件系统分析师的配置管理部分内容来介绍配置管理的工作&#xff08;原谅时间精力有限&#xff0c;原文基本已…

单例模式:懒汉饿汉线程安全问题

在我们前几篇文章中都了解了一些关于线程的知识&#xff0c;那么在多线程的情况下如何创建单例模式&#xff0c;其中的线程安全问题如何解决&#xff1f; 目录 1.什么是单例模式&#xff1f; (饿汉模式) 2.单例模式(懒汉模式) *懒汉模式与懒汉模式的对比 *如何解决懒汉模式…

蓝桥杯嵌入式第9届真题(完成) STM32G431

蓝桥杯嵌入式第9届真题(完成) STM32G431 题目 分析和代码 main.h /* USER CODE BEGIN Header */ /********************************************************************************* file : main.h* brief : Header for main.c file.* …

【开源】SpringBoot框架开发数字化社区网格管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、开发背景四、系统展示五、核心源码5.1 查询企事业单位5.2 查询流动人口5.3 查询精准扶贫5.4 查询案件5.5 查询人口 六、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数字化社区网格管理系统&#xf…

Prometheus服务器、Prometheus被监控端、Grafana、监控MySQL数据库、自动发现概述、配置自动发现、Alertmanager

目录 Prometheus概述 部署Prometheus服务器 环境说明&#xff1a; 配置时间 安装Prometheus服务器 添加被监控端 部署通用的监控exporter Grafana 概述 部署Grafana 展示node1的监控信息 监控MySQL数据库 配置MySQL 配置mysql exporter 配置mysql exporter 配置…

InternLM大模型实战-6.OpenCompass大模型评测

文章目录 前言笔记正文关于模型评测的三个问题为什么需要评测我们需要测什么怎么测试大语言模型 主流大模型评测框架OpenCompass大模型评测领域的挑战 前言 本文是对于InternLM全链路开源体系系列课程的学习笔记。【OpenCompass 大模型评测】 https://www.bilibili.com/video/…

【开源】SpringBoot框架开发木马文件检测系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 木马分类模块2.3 木马软件模块2.4 安全资讯模块2.5 脆弱点模块2.6 软件检测模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 木马分类表3.2.2 木马软件表3.2.3 资讯表3.2.4 脆弱点表3.2.5 软件检测表…

AtCoder Beginner Contest 340(A-G)

A - Arithmetic Progression (atcoder.jp) 1.思路&#xff1a;循环输出即可 2.代码&#xff1a; #include <bits/stdc.h> #define rep(i,z,n) for(int i z;i < n; i) #define per(i,n,z) for(int i n;i > z; i--) #define PII pair<int,int> #define fi f…

利用Windows10漏洞破解密码(保姆级教学)

前言: 本篇博客只是技术分享并非非法传播知识,实验内容均是在虚拟机中进行,并非真实环境 正文: 一.windows10电脑密码破解 1)开启windows10虚拟机,停留在这个页面 2&#xff09;按5次Shift键,出现这个粘滞键,如果没有出现的,则说明漏洞已经修复 3)重新启动,在这个页面的时候…

Tied Block Convolution: 具有共享较薄滤波器的更简洁、更出色的CNN

摘要 https://arxiv.org/pdf/2009.12021.pdf 卷积是卷积神经网络&#xff08;CNN&#xff09;的主要构建块。我们观察到&#xff0c;随着通道数的增加&#xff0c;优化后的CNN通常具有高度相关的滤波器&#xff0c;这降低了特征表示的表达力。我们提出了Tied Block Convolutio…

文件包含知识点详细总结

如果想看图片和观感更好的话,可以直接去我的github或者gitbook github:https://github.com/kakaandhanhan/cybersecurity_knowledge_book-gitbook.22kaka.fun gitbook:http://22kaka.fun description: 这里将通过参考文章和做题一起进行总结,并且文件包含漏洞,很多都利用了…

Hive调优——explain执行计划

一、explain查询计划概述 explain将Hive SQL 语句的实现步骤、依赖关系进行解析&#xff0c;帮助用户理解一条HQL 语句在底层是如何实现数据的查询及处理&#xff0c;通过分析执行计划来达到Hive 调优&#xff0c;数据倾斜排查等目的。 https://cwiki.apache.org/confluence/d…

C++ //练习 5.24 修改你的程序,使得当第二个数是0时抛出异常。先不要设定catch子句,运行程序并真的为除数输入0,看看会发生什么?

C Primer&#xff08;第5版&#xff09; 练习 5.24 练习 5.24 修改你的程序&#xff0c;使得当第二个数是0时抛出异常。先不要设定catch子句&#xff0c;运行程序并真的为除数输入0&#xff0c;看看会发生什么&#xff1f; 环境&#xff1a;Linux Ubuntu&#xff08;云服务器…