当前位置: 首页 > Linux

在实际应用中,union的妙用union

时间:2023-04-06 20:52:52 Linux

关键字union,又名union、union,union的声明类似于structure,但其行为却不同于structure。这里的行为主要是指它在内存中的体现。结构的每个成员占用不同的内存空间,而联合的所有成员在内存中共享相同的位置。简单看一下区别:structMyStruct{doublea;诠释乙;charc;};structMyStructvalue;unionMyUnion{doublea;诠释乙;charc;};unionMyUnion值;情况如下:可以看出结构变量中的3个成员相当于3个人,每个人必须住一个房间。优点是空间包容,但内存空间必须充分分配,不管房子住不下人。联合变量有3个成员。他们可以合住一个房间,但每个房间一次只能容纳一个成员,所以包容性不够。成员之间是互斥的,但是可以大大节省内存空间。需要注意的是union的长度是最大成员的大小,也就是本例中value.a的大小。它不仅仅指数据类型。如果MyUnion中定义了数组charc[10],此时union变量值的大小为10个字节。以上简单了解了union的基本定义。在实际应用中,我们一般使用结构体来定义由数据组成的结构变量。但是,每种数据类型的每个变量占用的空间是相似的,同时使用每个变量的要求是不同的。高场合(仅从内存占用)也可以灵活使用union。1.变量初始化初始化时,只需要初始化一个成员,即初始化列表中只有一个初始值。原因是联合体的所有成员共享一个首地址,默认情况下,这个初始值会被初始化为联合体变量的第一个成员。unionMyUnion{双a;诠释乙;charc;};//为第一个成员初始化unionMyUnionun1={5.0f};//初始化错误,不能初始化unionMyUnionun1={5.0f,10};//初始化其他位置的成员,可以指定初始化方法unionMyUnionun1={.b=10};//同结构体,也可以用一个union变量作为初始值,直接初始化给另一个同类型的union变量unionMyUnionun2=un1;2、数据位操作#includetypedefstruct{unsignedcharbit0:1;无符号字符位1:1;无符号字符位2:1;unsignedcharunsignedcharbit4:1;无符号字符bit5:1;无符号字符bit6:1;unsignedcharbit7:1;}bitValue;typedefunion{unsignedcharbytedata;位值位数据;}regValue;intmain(){regValue数据;data.bytedata=0x5A;printf("%d",data.bitdata.bit5);//读取第6位data.bitdata.bit7=1;//修改第8位return0;}可以看出,通过访问和修改union中定义的bitdata成员,可以间接访问和修改定义的bytedata的值,可以在嵌入式寄存器位操作中使用。3.与struct嵌套使用比如我们分别定义电视和空调的属性:structtvFeature//TVattribute{char*logo;//品牌价格;//priceintscreensize//屏幕尺寸intresolution//resolution}tvFeature;structtvFeaturetvfeature;structairFeature//空调属性{char*logo;//品牌价格;//priceintcoldcapacity;//制冷量inthotcapacity;//制热量}airFeature;structairFeatureairfeature;可见电视和空调有相同的属性,也有自己独特的属性。我们可以用家用电器的数据结构来统一定义。但是这样使用统一的数据结构会增加定义TV和空调的变量之间的耦合,tvfeature和airfeature没有用到的属性也会浪费内存空间。structhomeappliancesFeature//设备属性{char*logo;//品牌价格;//priceintscreensize//屏幕尺寸intresolution//resolutionintcoldcapacity;//制冷量inthotcapacity;//制热量}homeappliancesFeature;structhomeappliancesFeaturetvfeature;structhomeappliancesFeatureairfeature;所以可以用union来解决:structtvFeature//TVattribute{intscreensize//屏幕大小intresolution//resolution}tvFeature;structairFeature//空调属性{intcoldcapacity;//制冷量inthotcapacity;//制热能力}airFeature;structhomeappliancesFeature//设备属性{char*logo;//品牌长国;//国家联盟{structtvFeaturetvST;结构airFeatureairST;};};structhomeappliancesFeaturetvfeature;structhomeappliancesFeatureairfeature;如上所述,我们只需要一种结构就可以解决电视和空调不同性能的问题;structtvFeaturetvST和structairFeatureairST共享一个内存空间。在定义变量时,可以访问它们特有的属性,解决了内存浪费和变量耦合度高的问题。4、数据拷贝比如发送串口数据时,可以直接使用数据拷贝的方式打包发送数据,不需要将一个4字节的数据拆分成4个单字节的数据;否则在读取数据时,也没有必要将4个单字节数据再次移位拼接成一个4字节数据。typedefunion{uint8data8[4];uint32data32;}数据类型;uint32sendData=0x5A5AA5A5;uint32receiveData;dataTypecommSend;voidmain(void){uint8commData[128];//数据复制commData.data32=sendData;//发送数据,复制字节,不需要单独移位拆分commData.data32commData[0]=commSend.data8[0];commData[1]=commSend.data8[1];commData[2]=commSend。数据8[2];commData[3]=commSend.data8[3];//读取数据时,字节被复制,不需要拼接已经读取的4个单字节数据receiveData=commData.data32;}5.不同帧格式的数据分时传输例如,当需要针对不同的通信协议帧格式在同一个通信数据传输逻辑中发送数据时,可以这样定义数据结构。typedefstruct{uint8头;//帧头格式相同union//中间数据格式不同{struct//payloadType1{uint8cmd;uint8类型;uint8数据[5];uint8检查;}msgType1;结构//payloadType2{uint16cmd;uint8数据[8];uint16检查;}msgType2;uint8数据[10];//payloadType3}payloadType;uint8结束;//帧结束格式相同}frameType;顺便提一下:使用union时可以注意两点:1.数据大小字节序使用union时需要注意数据大小字节序问题,这取决于处理器的实际存储方式。大端存储是指高字节数据放在低地址。小端存储是指高字节数据放在高地址。如下面的例子,你可以知道所使用的处理器的存储方式:#includeunionUn{inti;charc;};unionUnun;intmain(){un.i=0x11223344;if(un.c==0x11){printf("bigendian\n");}elseif(un.c==0x44){printf("littleendian\n");}}2。指针访问因为在一个成员的不同长度的联合体中,分配给联合体的内存量取决于其最大成员的大小。如果内部成员的大小变化太大,在存储长度较短的成员时浪费的空间是相当可观的,在这种情况下,最好在联合中存储指向不同成员的指针,而不是直接存储成员本身。所有指针的长度都相同,可以解决浪费内存空间的问题。#includetypedefstruct{unsignedchara;intb;}stValue1;typedef结构{intc;无符号字符d[10];双e;}stValue2;//联合成员定义为指针成员unionUn{stValue1*ptrSt1;stValue2*ptrSt2;};intmain(){unionUn*info;信息->ptrSt1->a=5;info->ptrSt2->e=9.7f;}总之,在实际使用union过程中一句话总结:围绕成员互斥和内存共享这两个核心点灵活设计你的数据结构。更多技术内容和书籍资料,请关注公众号《明杰嵌入式》