C语言 C++中的union用法总结(包懂)

article/2025/10/7 16:11:53

开始的话

已经好长时间没有更新了,对不起自己,更对不起我亲爱的读者,同时也对不起自己开办的这个博客平台。忙,太忙了,忙于找工作,找一份好工作,纠结于去大城市闯呢,还是回到本省的首府城市。大家都在纠结这个问题,也希望大家和我讨论讨论。别的先不说了,都工作这么长时间了,还回过头来总结union,确实有点过分,要是和大家说我一直从事于C++开发,还不懂union,大家可能还真的不信。我们每天都在总结那些看似高端的东西,什么设计模式(当然我也有总结了)、重构(后期我也会说的了)了,却忽略了那些最基础,最根本的知识点。今天别人问我,我蒙了,所以,就有了这篇文章。

什么是union?

翻译过来说,就是共用体,或者也叫联合体。说到了union,也就是共用体,就不得不说一下struct了,当我们有如下的struct的定义时:

复制代码 代码如下:

struct student
{
     char mark;
     long num;
     float score;
};

关于struct的内存结构,将就会像下图所示这样(在x86机器上演示):

sizeof(struct student)的值为12bytes。但是,当我们定义如下的union时,

复制代码 代码如下:

union test
{
     char mark;
     long num;
     float score;
};

sizeof(union test)的值为4。这为什么呢?这就是需要说的。 有的时候,我们需要几种不同类型的变量存在在同一段的内存空间中,就像上面的,我们需要将一个char类型的mark、一个long类型的num变量和一个float类型的score变量存放在同一个地址开始的内存单元中。上面的三个变量,char类型和long类型所占的内存字节数是不一样的,但是在union中,它们都是从同一个地址存放的,也就是使用的覆盖技术,这三个变量互相覆盖,而这种使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构。上面定义的union类型的结构如下:

上面也说了,sizeof(union test)的值为4。那为什么是4呢?大体上来说,结构体struct所占用的内存为各个成员的占用的内存之和(当然也需要考虑内存对齐的问题了)。而对于union来说,在谭浩强的《C语言程序设计》中这么说:union变量所占用的内存长度等于最长的成员的内存长度。很显然,这是不对的,对于union所占用的内存大小,需要考虑内存对齐的问题。这就是为什么sizeof(union test)的值为4啦。

C中使用union

说的再好,再多,终归都是要在使用的,下面就好好的说说C中使用union。和struct一样,union只有先定义了共用体变量才能引用它。而且不能直接引用共用体变量,而只能引用共用体变量中的成员。就像我上面定义的union test。我们不能像下面这样直接引用union:

复制代码 代码如下:

union test a;
printf("%d", a);

这种直接引用是错误的,由于a的存储区有好几种类型,分别占不同长度的存储区,仅写共用体变量名a,这样使编译器无法确定究竟输出的哪一个成员的值。所以,应该写成下面这样:

复制代码 代码如下:

printf("%d", a.mark);

同时,在使用union的时候,我们还需要注意以下的几点:

1.同一个内存段可以用来存放几种不同类型的成员,但在每一个时刻只能存在其中一种,而不是同时存放几种。也就是说,每一瞬间只有一个成员起作用,其它的成员不起作用,即不是同时都存在和起作用。

2.共用体变量中起作用的成员是最后一个存放的成员,在存入一个新的成员后,原有的成员就失去作用。比如以下的代码:

复制代码 代码如下:

#include <iostream>
using namespace std;
 
union test
{
     char mark;
     long num;
     float score;
}a;
 
int main()
{
     // cout<<a<<endl; // wrong
     a.mark = 'b';
     cout<<a.mark<<endl; // 输出'b'
     cout<<a.num<<endl; // 98 字符'b'的ACSII值
     cout<<a.score<<endl; // 输出错误值
 
     a.num = 10;
     cout<<a.mark<<endl; // 输出空
     cout<<a.num<<endl; // 输出10
     cout<<a.score<<endl; // 输出错误值
 
     a.score = 10.0;
     cout<<a.mark<<endl; // 输出空
     cout<<a.num<<endl; // 输出错误值
     cout<<a.score<<endl; // 输出10
 
     return 0;
}

所以,在使用union的时候,要十二分的小心的。

3.由于union中的所有成员起始地址都是一样的,所以&a.mark、&a.num和&a.score的值都是一样的。

4.不能把union变量作为函数参数,也不能使函数带回union变量,但可以使用指向union变量的指针。

5.union类型可以出现在结构体类型定义中,也可以定义union数组,反之,结构体也可以出现在union类型定义中,数组也可以作为union的成员。

按理说,总结到这里,C语言中的union也就没什么更多的要说了。但是,有一种东西叫做C++,在这个C++中有一种东西叫做类。

当union遇到对象

就单单C中的union,上面的总结已经够用了,但是,现在偏偏又有一个叫做C++的东西;当union遇到了C++中的对象时,一切又变得剪不断,理还乱。上面总结的union使用法则,在C++中依然适用。本来union本就是从C语言中的,如果我们在C++中继续按照C语言的那种方式使用union,那是没有问题的。如果我们在union中放一个类的对象呢?结果会怎么样?比如有以下代码:

复制代码 代码如下:

#include <iostream>
using namespace std;
 
class CA
{
     int m_a;
};
 
union Test
{
     CA a;
     double d;
};
 
int main()
{
     return 0;
}

可以看到,没有问题;如果我们在再类CA中添加了构造函数,或者添加析构函数,我们就会发现程序就会出现错误。由于union里面的东西共享内存,所以不能定义静态、引用类型的变量。由于在union里也不允许存放带有构造函数、析构函数和复制构造函数等的类的对象,但是可以存放对应的类对象指针。编译器无法保证类的构造函数和析构函数得到正确的调用,由此,就可能出现内存泄漏。所以,我们在C++中使用union时,尽量保持C语言中使用union的风格,尽量不要让union带有对象。

结束的话

我们都在玩那些高大上的东西,猛回头,发现身后却又一个大坑。打开尘封了多年的《C语言程序设计》(谭浩强著),小心翼翼的拭去封面上的尘土,思绪立刻被拉回到大一。那些年,我那清纯的大一。对大学的憧憬,对计算机的好奇,对编程的未知,就是这本书,这本该死的《C语言程序设计》,把我带上了“程序猿”这条不归路。说多了,都是泪,当你看我这篇文章时,你应该懂我的。CodeMonkey~~~,这条不归路,且行且珍惜。

===修改日志===

2014年9月11日 删除了文中“不能把union变量作为函数参数,也不能使函数带回union变量,但可以使用指向union变量的指针。”这样的描述,非常感谢Cassie_Lcy的指正,而且还在评论中附上了验证代码,非常感谢;同时,我也非常抱歉,对于这点没有验证过的知识,就进行了总结,对大家造成了一定的误导,sorry。一定要注重求学的严谨性。

                        <div class="art_xg"><b>您可能感兴趣的文章:</b><ul><li><a href="/article/125134.htm" title="C语言中联合体union的实例详解" target="_blank">C语言中联合体union的实例详解</a></li><li><a href="/article/91141.htm" title="C语言 共用体(Union)详解及示例代码" target="_blank">C语言 共用体(Union)详解及示例代码</a></li><li><a href="/article/75794.htm" title="C语言编程中的联合体union入门学习教程" target="_blank">C语言编程中的联合体union入门学习教程</a></li><li><a href="/article/205661.htm" title="C语言关键字union的定义和使用详解" target="_blank">C语言关键字union的定义和使用详解</a></li></ul></div></div>

http://chatgpt.dhexx.cn/article/YFU7lZuw.shtml

相关文章

php union用法,SQL Union用法是什么?

sql union用法是什么&#xff1f; sql union用法的总结&#xff1a; UNION 运算符将多个 SELECT 语句的结果组合成一个结果集。 (&#xff11;)使用 UNION 须满足以下条件&#xff1a; &#xff21;&#xff1a;所有查询中必须具有相同的结构(即查询中的的列数和列的顺序必须相…

mysql union语法,mysql中的union用法

UNION在mysql中被称为集合操作,操作类型分为两种:UNION DISTINCT 和 UNION ALL;注意:UNION和UNION DISTINCT是一样的功能。UNION功能为合并多个查询的结果并去重,UNION ALL的功能为合并多个查询的结果不去重。 集合操作时,两边的输入必须拥有相同的列数,如果数据类型不…

mysql得union使用方法_mysql中Union All使用方法

在mysql数据库使用UNION 时&#xff0c;会把结果集中重复的记录删掉&#xff0c;也正因为做了去重操作&#xff0c;所以效率相对Union All来讲稍微低一点&#xff0c;使用UNION ALL &#xff0c;MySQL 会把所有的记录返回&#xff0c;效率高于UNION。本文向大家介绍UNION ALL的…

SQL 中union的使用

采用where的解法 select name,population,area from World where area>3000000 or population>25000000 ;使用union的解法 select name,population,area from World where area>3000000 union select name,population,area from World where population>2500000…

C语言共用体(C语言union用法)详解

转载重点&#xff1a;共用体的所有成员占用同一段内存&#xff0c;修改一个成员会影响其余所有成员。图形分析影响过程 通过前面的讲解&#xff0c;我们知道结构体&#xff08;Struct&#xff09;是一种构造类型或复杂类型&#xff0c;它可以包含多个类型不同的成员。在C语言中…

C语言 union用法

我们知道结构体&#xff08;Struct&#xff09;是一种构造类型或复杂类型&#xff0c;它可以包含多个类型不同的成员。在C语言中&#xff0c;还有另外一种和结构体非常类似的语法&#xff0c;叫做共用体&#xff08;Union&#xff09;&#xff0c;它的定义格式为&#xff1a; …

c语言union(c语言union用法)

C语言-程序运行结果是&#xff1f;main(){unionstu{lon 我的机器&#xff0b;vc6运行的结果是12 我的理解是首先取最长的b的长度&#xff0c;但是b的长度比我的机器字长(32位即4个字节)整数倍要短&#xff0c;则sizeof(stu)的长度是12 不知道你的机器是不是64位的 如果是则证…

quartz mysql 配置_quartz的数据库配置

Quartz.net官方开发指南 第九课&#xff1a; JobStore JobStore负责保持对所有scheduler “工作数据”追踪&#xff0c;这些工作数据包括&#xff1a;job(任务),trigger(触发器),calendar(日历)等。为你的Quartz scheduler选择合适的JobStore是非常重要的一步&#xff0c;幸运的…

java 灵活配置quartz

项目背景&#xff1a; 最近项目上遇到个需求&#xff0c;需要我们在特定的事件做邮件和短信的发送。但时间并不固定&#xff0c;是根据用户配置的时间表来进行的定时发送任务。有点像闹钟&#xff0c;你设置的时间到了就响。这里我们采取的是每天凌晨定时取数据库里的时间表信…

java quartz配置_java quartz简单使用

1.在项目里引入quartz org.quartz-scheduler quartz 2.3.0 2.quartz的简单实例 package com.example.quartz_demo; import org.quartz.JobDetail; import org.quartz.Scheduler; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrig…

SpringBoot - 集成Quartz框架之常用配置(二)

文件约定 在Quartz发布的JAR包的org.quartz包下&#xff0c;包含了一个命名为quartz.properties的配置文件并提供了默认属性&#xff0c;如果需要调整默认配置&#xff0c;则可以在类路径下建立一个新的quartz.properties&#xff0c;它将自动被Quartz加载并覆盖默认值。如果使…

浅析Quartz的集群配置

1、基本信息&#xff1a; Quartz是一个开源的作业调度框架&#xff0c;它完全由java写成&#xff0c;并设计用于J2Se和J2EE应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征&#xff0c;如&#xff1a;数据库支…

SpringBoot2集成Quartz配置独立数据源

需求说明 Quartz配置需要部署独立的表结构&#xff0c;但是经常存于业务表之间&#xff0c;有些时候可能需要与业务表分开配置&#xff0c;所以在此给Quartz配置独立的数据源 一.版本介绍 Springboot版本为2.1.6 多数据源配置使用druid进行配置,数据库使用的为Oracle11g,如果使…

Quartz配置和运用详解

本文转自&#xff1a;http://topmanopensource.iteye.com/blog/1123824 最近工作需要学习quartz&#xff0c;那么必须首先了解三个概念&#xff1a; 调度器&#xff1a;负责调度作业和触发器&#xff1b; 触发器&#xff1a;设置作业执行的时间、参数、条件等&#xff1b;&…

Springboot——quartz简单配置和使用

文章目录 简单maven项目配置依赖配置编写处理类编写测试类 Springboot 项目配置依赖引入编写任务具体处理类编写配置类注意事项测试 简单maven项目配置 依赖配置 springboot项目中增加如下的quartz依赖信息&#xff1a; <!-- https://mvnrepository.com/artifact/org.qua…

Quartz配置文件quartz.properties加载

Quartz配置文件quartz.properties加载 前天&#xff0c;同事来问我&#xff0c;quatz任务调度的qurtaz.properties配置文件是如何加载的&#xff0c;项目是老大写的&#xff0c;我没看过代码&#xff0c;于是去翻了一遍源码&#xff0c;终于找到了配置的加载地方&#xff0c;让…

quartz mysql 配置_Quartz配置

1. Quartz主要配置 属性名称是否必选类型默认值说明 org.quartz.scheduler.instanceName 否 String QuartzScheduler Schedule调度器的实体名字 org.quartz.scheduler.instanceId 否 String NON_CLUSTERED Schedule调度器的实体的Id,必须唯一。 1. 当你想生成intanceId的时候可…

(AnyWhere-)安卓版“捷径”

下载 久闻酷安大名&#xff0c;下了酷安App&#xff0c;真是发现了新大陆。可以的&#xff0c;看上了AnyWhere-&#xff0c;下载试试 AnyWhere-下载地址 - 酷安 使用教程 一开始看的是这篇文章入坑的 真的不用羡慕iOS&#xff01;神奇APP“AnyWhere”让安卓也能玩“捷径” …

Anywhere,一个随启随用的静态服务器

现在用webpack也很少用到这种启动服务&#xff0c;偶尔做个小demo还是可以用用 Anywhere是一个随启随用的静态服务器&#xff0c;它可以随时随地将你的当前目录变成一个静态文件服务器的根目录。 一、首先得有node 如果没有的话&#xff0c;直接去官网下载安装包或者用brew …

Anywhere 随启随用的静态文件服务器

1.Anywhere 随启随用的静态文件服务器 ----利用nodeJs anywhere搭建本地服务器环境一&#xff1a;首先去nodeJs官网下载最新版nodeJs https://nodejs.org/en/ 安装成功后winr打开cmd 输入node -help 或者node -v查看是否安装成功 二&#xff1a;装好后输入 npm install anywhe…