联合体结合位域使用技巧

Posted lrw998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了联合体结合位域使用技巧相关的知识,希望对你有一定的参考价值。

偶然在代码中看到这样一个定义:

typedef union
{
	unsigned char byte;             /**< the whole byte */

	struct
	{
		unsigned int retain : 1;    /**< retained flag bit */
		unsigned int qos : 2;       /**< QoS value, 0, 1 or 2 */
		unsigned int dup : 1;       /**< DUP flag bit */
		unsigned int type : 4;      /**< message type nibble */
	} bits;
} Header;

我在实际开发的时候很少用到和看到联合体和位域的出现,正好借这个机会学习一下。


#位域

​ 使用位域的主要目的是节约存储空间,可能某些情况下成员变量只能取几个值,那么则不需要使用一个字节甚至更大的空间去存放它。

​ 举个例子,在上面的结构体 bits 中,qos 这个成员变量只能取0,1,2这三个值,那么我们可以在其定义后面加: 2 来表示其只占用2 bit 的内存,故取值范围是[0, 3],满足我们的要求。其它变量如 retain,dup 仅可取0或1,则只需给他们分配1 bit 的内存就可以。这样下来,整个 bits 结构体仅占用一个字节内存。

#联合体

​ 联合体的关键字是union,它与结构体的区别是:联合体的所有成员占用同一块的内存,这块内存的大小(联合体的大小)取决于成员之中占用空间最大的。且联合体中的所有成员变量的起始地址相同,画个图来解释一下:

image-20210519192522914

​ 图中表示的是一个Header实体的内存占用情况,可以看到成员变量byte和结构体bits的起始地址是相同的,均为该联合体实体的起始地址。由于两个成员的占用空间都分别是1 Byte,故整个Header实体的占用空间大小也是1 Byte。


​ 这样做的好处就是当我们处理一帧报文的时候,由于用于存储报文的内存大多是按字节存储的,故可以直接对byte成员赋值,不需要再对每个字节进行切割再分别赋值。

image-20210519193814839

以上是关于联合体结合位域使用技巧的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Autosar 中使用位域创建联合实现数据类型?

C++基础语法梳理:位域以及 union 联合!小知识分享

C语言自定义类型一网打尽(结构体位段/位域枚举联合体)

澄清 C 中的位域排序语义

如何将结构从 C++ 迁移到 C#

为啥位字节序是位域中的一个问题?