干货结构体联合体嵌套使用的一些实用操作
结构体、联合体是C语言中的构造类型,结构体我们平时应该都用得很多。但是,对于联合体,一些初学的朋友可能用得并不多,甚至感到陌生。我们先简单看一下联合体:
在C语言中定义联合体的关键字是 union 。
定义一个联合类型的一般形式为: union 联合名 { 成员表 };
成员表中含有若干成员,成员的一般形式为: 类型说明符 成员名 。其占用的字节数与成员中最大数据类型占用的字节数。
下面我们一起看一下结构体、联合体结合使用在C语言、嵌入式中的一些实用技巧。 1、应用于管理不同的数据
示例代码: /* 公众号:嵌入式大杂烩 */ enum DATA_PKG_TYPE { DATA_PKG1 = 1, DATA_PKG2, DATA_PKG3 }; struct data_pkg1 { // ... }; struct data_pkg2 { // ... }; struct data_pkg3 { // ... }; struct data_pkg { enum DATA_PKG_TYPE data_pkg_type; union { struct data_pkg1 data_pkg1_info; struct data_pkg2 data_pkg2_info; struct data_pkg3 data_pkg3_info; }data_pkg_info; };
这里把struct data_pkg1、struct data_pkg2、struct data_pkg3三个结构体放到了struct data_pkg这个结构体里进行管理,把data_pkg_type与union里的三个结构体建立一一对应关系,我们需要用哪一结构体数据就通过data_pkg_type来进行选中。在进行数据组包的时候,先给data_pkg_type进行赋值,确定数据包的类型,再给对应的union里的结构体进行赋值;在进行数据解析的时候,通过data_pkg_type来选择解析哪一组数据。
思考一下,如果在union里面再嵌套一层union会怎么样?会变得更复杂?以前的话,我会觉得越嵌套会越复杂,我也很抵制这种不断嵌套的做法。但后来看了我同事的设计之后,我惊呆了!这可太秀了,他就是这么嵌套使用把原本复杂的系统数据管理得明明白白的。我们看他怎么设计的(看个大概的图):
可以看到最左边和最右边这就建立起了一一对应关系,我们的模块很多,数据很多,但是在这样的设计中显得很清晰、很容易维护。 2、寄存器、状态变量封装
我们看一看TI的寄存器封装是怎么做的:
所有的寄存器被封装成联合体类型的,联合体里边的成员是一个 32bit 的整数及一个结构体,该结构体以位域的形式体现。这样就可以达到直接操控寄存器的某些位了。比如,我们要设置PA0 引脚的GPAQSEL1 寄存器的[1:0] 两位都为1,则我们只操控两个bit 就可以很方便的这么设置:GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 3
或者直接操控整个寄存器: GpioCtrlRegs.GPAQSEL1.all |=0x03
如果不是工作于芯片原厂,寄存器的封装应该离我们很远。但我们可以学习使用这种方法,然后用于我们的实际应用开发中。
下面就看一种实际应用: 管理一些状态变量 。
示例代码: union sys_status { uint32 all_status; struct { bool status1: 1; // FALSE / TRUE bool status2: 1; // bool status3: 1; // bool status4: 1; // bool status5: 1; // bool status6: 1; // bool status7: 1; // bool status8: 1; // bool status9: 1; // bool status10: 1; // // ... }bit; };
之前记得群里有一位小伙伴问系统有几十个状态变量需要管理,怎么做比较好。如上例子就是比较好的一种管理方法。 3、数据组合/拆分、大小端(1)验证大小端/* 公众号:嵌入式大杂烩 */ #include typedef unsigned int uint32_t; typedef unsigned char uint8_t; union bit32_data { uint32_t data; struct { uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }byte; }; int main(void) { union bit32_data num; num.data = 0x12345678; if (0x78 == num.byte.byte0) { printf("Little endian "); } else if (0x78 == num.byte.byte3) { printf("Big endian "); }else{} return 0; }运行结果:
(2)数据组合、拆分
这其实也就是上一篇文章 面试题 | 获取整数各个字节 介绍的。在数据组合与拆分之前首先需要确实当前平台的大小端。比如 小编使用的平台是小端模式 。① 把0x12345678拆分成0x78、0x56、0x34、0x12:/* 公众号:嵌入式大杂烩 */ #include typedef unsigned int uint32_t; typedef unsigned char uint8_t; union bit32_data { uint32_t data; struct { uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }byte; }; int main(void) { union bit32_data num; num.data = 0x12345678; printf("byte0 = 0x%x ", num.byte.byte0); printf("byte1 = 0x%x ", num.byte.byte1); printf("byte2 = 0x%x ", num.byte.byte2); printf("byte3 = 0x%x ", num.byte.byte3); return 0; }运行结果:
② 把0x78、0x56、0x34、0x12组合成0x12345678:/* 公众号:嵌入式大杂烩 */ #include typedef unsigned int uint32_t; typedef unsigned char uint8_t; union bit32_data { uint32_t data; struct { uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }byte; }; int main(void) { union bit32_data num; num.byte.byte0 = 0x78; num.byte.byte1 = 0x56; num.byte.byte2 = 0x34; num.byte.byte3 = 0x12; printf("num.data = 0x%x ", num.data); return 0; }运行结果:
但是数据组合与拆分有更好的方法: 移位操作 。篇幅有限不再贴出代码,详细代码可参考:面试题 | 获取整数各个字节 、嵌入式、C语言位操作的一些常见用法归纳 两篇文章。4、结构体 & 缓冲区#define BUF_SIZE 16 union protocol_data { uint8_t data_buffer[BUF_SIZE]; struct { uint8_t data1; uint8_t data2; uint8_t data3; uint8_t data4; // ... }data_info; };
这种应用得很广泛,用于自定义通信协议。struct里面的内容可以设计得很简单,比如全是有用的数据,或是设计得很复杂,包含一些协议头尾、包长、有效数据、校验等内容。但无论如何,我们组包发送的过程是 填充结构体->发送data_buffer ;反之接收数据解析的过程就是接收数据存于data_buffer->使用结构体数据 。5、传输浮点数据union f_data { float f; struct { unsigned char byte[4]; }; }
类似的,使用这样子的方法可以用于传输浮点数,更具体地不再展开,网络上有很多这一块的资料。感兴趣的朋友可以自己操作验证验证。
1024G 嵌入式资源大放送!包括但不限于C/C++、单片机、Linux等。私信回复 1024,即可免费获取!
为什么这么多人黑小米?是真的不行吗?也不是,国产手机基本上都是一套的供应链,没什么大区别,唯一改动的可能就是外观,小米之所以总被黑,是因为动了很多人的蛋糕,这也很正常不是小米的手机不行,而是小米自从开始往高端发力之后
3000内台式电脑组装清单推荐?这个配置比较好写不要考虑11和12代CPU,主要是主板比较贵,不要考虑显卡,有了这个标准就很简单了!CPUi310100680(散片)主板b460450内存金士顿26008GB26
华为未来能成为世界10强吗?就算没有美国的制裁,华为也几乎不可进入世界十强。以完全竞争行业成员的身份,要成为世界上最顶尖的公司是难度那不是一般的大,从历史上来看,这些公司都是代表了一个时代。以前是石油化工时代
消防应急智能疏散哪个厂家做得好?知道的告诉下?中智盛安呀,他们家的消防应急智能疏散系统在很多行业都有不错的应用,国内的知名老品牌了,市场口碑也一直都很不错的,楼主你要是有这方面需求的话可以到他们官网上去详细了解下咯!推荐给你中
SEM和SEO有什么区别?两个观点,可以思考一下第一,seo和sem是否可以完全分开当两个事情来看或者对比?第二,seo和sem效果对比是否可以做到科学准确?针对第一个假设,我的看法是不要被以前的思路影响,
每天跑步跑多远最好?有什么依据吗?我是昆明山水,题主问每天跑五公里七公里还是十公里好?这个距离可以理解为以锻炼身体为主的健康跑。那么,我认为,每天运动40分钟到60分钟对身体健康最有锻炼效果。至于跑多少距离可以根据
我现在好迷茫,不想打工,也不知道该做什么,谁能给我指一条路?三百六十行,行行岀状元,不想打工,打铁必须自身硬。如果你有足够本钱,可以自已开公司当老板,或者投资房地产。没有足够底气,还是先努力打工赚钱,积累到一定资金才考虑不打工问题。不想打工
当今人类认知最少同时也最无法最不情愿去探索的领域是什么?这个领域几乎无法触及。谢谢!应该是脑神经元,它是当今人类与其它生物最不同的地方。如单极神经元,双极神经元,多极神经元。脑突触,突触小泡工作原理。包括线粒体,神经元核仁,及大脑储存,
因央视315曝光中关村在线道歉乐视表示不愿成为不法分子的工具电动狗3月15日晚,央视315晚会报道了软件下载平台高速下载陷阱的问题。记者在PC6下载站桔梗下载站腾牛网ZOL软件下载等平台下载软件时都出现类似的问题,这些下载平台,使用的是百助
长虹控股集团2022年度计划招聘3200人,涉及新能源半导体等领域3月14日,记者从长虹控股集团获悉,2022年度,长虹计划面向国内外招聘3200人,同比增加超60,涵盖智能家电人工智能半导体计算机存储新能源等领域的技术研发工程类和管理类等岗位。
为什么俄罗斯不怕芯片卡脖子?杨净梦晨发自凹非寺量子位公众号QbitAI怎么一个国家被卡脖子了,画风竟然是这样?时间回到十几天前,美国一声令下,英特尔AMD台积电,三星几乎当下所有主流厂商都挨个制裁了个遍。俄罗