汉扬编程 C语言入门 C/C++语言编程系列005——联合体union的妙用

C/C++语言编程系列005——联合体union的妙用

联合体union的基本概念在C/C++语言中,有时需要在同一段内存单元中存放不同类型的变量,如把一个整形变量int、一个字符型变量char和一个双精度实型变量double放在同一个地址开始的内存单元中,这3个变量虽然在内存中占的字节数不同,但都从同一地址开始,使用覆盖技术,后一个数据覆盖了前面的数据。这便是联合体union(或者叫共用体)诞生的目的所在。其主要特点是:

C/C++语言编程系列005——联合体union的妙用

union中可以定义多个成员,union的大小由最大的成员的大小决定union成员共享同一块大小的内存,一次只能使用其中的一个成员对union某一个成员赋值,会覆盖其他成员的值从上面也可以看出,联合体与C语言中的结构体有一些相似之处,但两者有本质上的不同。在结构体中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在联合体中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。

C/C++语言编程系列005——联合体union的妙用

联合体union的定义方式在C/C++语言中,常见的3种定义方式如下:

C/C++语言编程系列005——联合体union的妙用

声明的同时定义变量先声明,再定义变量匿名定义变量下图给出了3种定义方式的一个例子:

C/C++语言编程系列005——联合体union的妙用

C/C++语言编程系列005——联合体union的妙用

联合体union的使用例子使用联合体类型,可以实现一些我们意想不到或其它编程语言很难做到的功能,下面给出2个例子。

(1) 将一个32位的整型数拆分为4个单字节的数

如将一个数0x12345678拆分为4个单字节的数为:0x78、0x56、0x34、0x12,则主要实现代码如下:

使用上面代码,可将0x12345678按地址顺序从低到高依次拆分为4个单字节的数:0x78、0x56、0x34、0x12。

(2) 判断当前操作系统的字节序的大、小端问题

主要原理为:在联合体中定义一个4字节整数i和一个单字节整数ch,且赋值i为1(16进制表示为0x00 00 00 01),利用联合体中所有变量共享内存区域的特性,若系统是小端序,则该联合体的低地址端存放的是数值i的低位字节(0x01),反之,若系统是大端序,则存放的是数值i的高位字节(0x00),那么可根据ch的值(存放在该联合体的低地址端,非0即1)来判断当前系统的字节序问题。对应的实现函数代码如下:

对于上面2个例子,完整的实现代码如下:

运行结果如下图所示:

欢迎加关注,共同交流。

C语言关键字union的使用

在C语言中关键字union和struct用法是一样的,而且在项目中struct随处可见。在我的专栏"嵌入式入门——C语言入门到深入"中我详细的讲解了它们的异同。很多人编码了多年也许会认为有struct就够了,要union干嘛,感觉union的存在有些鸡肋,但是事实真的是这样吗?下面让我来告诉你哪些应用场景union是不能被struct替代的,而且使用union也是唯一能够很好的解决问题的。

C/C++语言编程系列005——联合体union的妙用

我在专栏里第十五章 C语言位操作里介绍过位域这个知识点,里面我也书写了个非常经典的例程。经常和微控制芯片(MCU)打交道的嵌入式工程师对位操作一定不陌生,也经常接触各类的中断(中断是指在程序运行的过程中,出现一些"异常"情况,需要MCU干预并转入中断处理情况,处理完后重新运行原程序的过程。计算机的运行就是靠中断来维持的,键盘中断,鼠标中断,屏幕显示中断,扬声器中断等等)。现在我使用联合和位域相结合的办法可以很好的表示它们。比如我定义如下联合体:

C/C++语言编程系列005——联合体union的妙用

C/C++语言编程系列005——联合体union的妙用

当我们要去使用各个中断的时候,直接使用uint8_t类型的数据很不直观,但是使用里面的位域却可以很好的表达。此时只能使用联合体而不能使用结构体。

C/C++语言编程系列005——联合体union的妙用

现在让我们来看看怎么使用它。我先定义两个开关中断的宏,定义如下:

C/C++语言编程系列005——联合体union的妙用

C/C++语言编程系列005——联合体union的妙用

使用如下:

从上图可以看出,位域结合联合使用是非常好表达的,在代码里能很直观的表达我们自己的意图。下面附上示例的完整代码:

我当前使用的是deepin操作系统,程序运行结果显示为"Interrupts: 0xC0.",至于数据存储模式大小端的知识我在专栏里也介绍过,在此不再赘述。

顺便说下,有人可能会认为在消息队列使用时,由于发送的各个消息各不相同,同一时刻只能发送一个消息,因此可以使用联合来节省空间,这么一看貌似也对,的确可以如此。

但是你想过没有,现在的计算机不差你那点存储空间,可以大胆的去使用结构体也是可以的。如果我使用通用指针是不是是最佳的方案呢?定义如下:

通用指针怎么用,有什么妙用?我在专栏里讲解过该知识点后使用了比较多的示例去使用它,要多用多体会通用指针的妙用才好。

通过这一篇文章,希望你可以对联合有了一个更加深刻的认识,知道什么场景才是最适合它的。

本文来自网络,不代表汉扬编程立场,转载请注明出处:http://www.hyzlch.com/cjia/6054.html

输出什么C语言 printf(\”c?

C++多线程编程之创建线程篇

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

返回顶部