联合体union能解决什么问题?

《《《《《正文》》》》》


 

《结构体的不足》

在C语言中,如果要你描述一辆车的属性,最快最简洁的方法就是构建结构体:

struct car_info{     char *logo; //品牌     long country; //国家     int price;   //价格     char type; //类型};

如上定义的结构体就可以很方便的描述一辆车的信息,而且多辆车的话只需新增一个car_info定义的变量而已,方便且简洁明了!

如果后续还增加车的属性的话,只需在结构体中增加一个参数就可以了,如下:struct car_info{

     ...    int color; //颜色};

但是有没有想过,新能源车和传统型车之间的属性不同,就是新能源有的参数在传统型车上是没有的,比如电池充电速度、电池容量等属性;同样,传统型车上有的属性是新能源车上没有的,比如用油类型等属性;

那有人说,简单,新能源和传统车型各开一个结构体:

struct NewCar_info{     char *logo; //品牌     long country; //国家     int price;   //价格     char type; //类型     int  timer;//充电速度     int  batery; //电池容量};
struct OldCar_info{     char *logo; //品牌     long country; //国家     int price;   //价格     char type; //类型     int  oiltype;//用油类型     int  Oilspend; //耗油量};

这样子,只要调用定义就可以了,如下:

// 新能源车型struct NewCar_info Ninfo;// 传统车型struct OldCar_info Oinfo;

不过,在程序里讲究封装这个概念,我们往往喜欢把相同的东西封装打包,这样能节省很多空间,而且下次更改也只需更改封装里的东西,不必全代码一个一个的更改,所以干脆就写成一个结构体吧,如下:

struct NOCar_info{     char *logo; //品牌     long country; //国家     int price;   //价格     char type; //类型     int  timer;//充电速度     int  batery; //电池容量     int  oiltype;//用油类型     int  Oilspend; //耗油量};

如上结构体,依然可以描述新能源车型和传统车型,如下:

// 新能源车型struct NOCar_info Ninfo;// 传统车型struct NOCar_info Oinfo;

上面只要特殊处理一下,新能源不能访问传统属性,传统不能访问新能源的属性就可以了,但是他们之间耦合会增加很多,这样也是行得通的;

但是因为今天是讲union,自然要挑骨头,有人会说,嵌入式本来内存就紧张,上面这种方法浪费内存,听起来无可反驳,那怎么办?


《union大显身手》

union的出现就很好解决了浪费内存和耦合高的问题,我们来看看,它是怎么解决的。

先来看看union的语法:

struct NewCar_info{     int  timer;//充电速度     int  batery; //电池容量};struct OldCar_info{     int  oiltype;//用油类型     int  Oilspend; //耗油量};struct NOCar_info{     char *logo; //品牌     long country; //国家     int price;   //价格     char type; //类型    union{        struct NewCar_info NCar;        struct OldCar_info OCar;    };};

我们来看NOCar_info中的union内的参数,意思就是其中的2个struct公用一块内存,什么意思呢?就是你改变 struct NewCar_info NCar中的值,struct OldCar_info OCar也会被同样改变,且是同一个内存同一个值,反过来亦是如此,因此成为共用体、联合体;

如上我们只需一个结构体,就可解决新能源和传统车型自己的属性不同问题;

// 新能源、传统struct NOCar_info NO_Car;

若要访问新能源车型的充电时间和电池容量,可如下操作:

​​​​​

timer = NO_Car.NCar.timer;batery = NO_Car.NCar.batery;

若要访问传统车型的用油类型和油耗量,可如下操作

oiltype = NO_Car.OCar.oiltype;Oilspend = NO_Car.OCar.Oilspend;

这样子就解决了,上面的浪费内存,耦合读高的问题;

 

union当然也有其他的用处,主要原理是利用公用内存这一个特性;


 

《我常用union的场景》

串口发送往往是按字节发送,因此一个32位的数据,需要拆分成4个字节,然后依次发送;按往常,我们做位运算可以得出4个字节的数据,但是union就可以直接取出,具体实现伪代码如下:​​​​​​​

typedef union{  uint8_t    B8[4];  uint16_t   B16[2];  uint32_t   B32;}B32_B8_TypeDef;
uint32_t Send_Data = 0x12345678;B32_B8_TypeDef Uart_Send;
void main(void){    //数据复制    Uart_Send.B32 = Send_Data;        //字节复制    Uart[0]= Uart_Send.B8[0];    Uart[1]= Uart_Send.B8[1];    Uart[2]= Uart_Send.B8[2];    Uart[3]= Uart_Send.B8[3];    //发送数据}

《《《《《END》》》》》

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值