数据结构学习之 union 共用体(union 到底有什么用?)

1、引言

共用体常用来节省内存,特别是一些嵌入式编程,内存是非常宝贵的!
共用体也常用于操作系统数据结构或硬件数据结构!
union 在操作系统底层的代码中用的比较多,因为它在内存共享布局上方便且直观。所以网络编程,协议分析,内核代码上有一些用到 union 都比较好懂,简化了设计。

共用体(union)是一种数据格式,它能够存储不同类型的数据,但是只能同时存储其中的一种类型。主要用处分以下几个方面

2、测试大小端模式

大小端不同,则存储的方式也存在差别,比如int需要4个字节,而char只需要1个字节,根据1个字节所在的具体位置即可判定CPU的模式。

union TestCPU
{
     int i;
     char ch;
};
void testCPUMode(void)
{
    union TestCPU Test;
    Test.i = 1;
    if(Test.ch == 1)
    {
      //这个CPU是小端模式
    }
    else
    {
       //这种情况下就是大端模式
    }
}

如果是 little endian 字节序的话,那个Test.i = 1;的内存从小到大依次放的是:0x01 0x00 0x00 0x00,如是,按照i的起始地址变成按照char 方式(1字节)存取,即得c = 0x01;
反之亦然

2.1 大小端转换函数

/*1.宏定义*/
#define Little_To_LargeOfEndian(x) (((x&0xff)<<24)|((x&0xff00)<<8)| \
((x&0xff0000)>>8)|((x&0xff000000)>>24))      
 //1.四个字节的排放顺序要弄清楚

/*2.写成函数*/
void Little_To_LargeOfEndian(int x)
{
    char a,b,c,d;
    a=(char)(x&0xff);
    b=(char)((x&0xff00)>>8); //3. 字符类型转换的优先级高于移位,所以用括号把移位操作括起来~
    c=(char)((x&0xff0000)>>16);
    d=(char)((x&0xff000000)>>24);
    //printf("0x%x 0x%x 0x%x 0x%x\n",a,b,c,d);
    x=(a<<24)|(b<<16)|(c<<8)|d;
    printf("after transfered x is 0x%x\n",x);
}

3、实现多种数据类型之间转换

3.1 案例一

union Type
{
   int i;
   char ch;
   long lint;
   ....
};

...
union Type type;

这样各种类型的数据共用存储空间,很方便的实现了不同数据类型之间的转换,不需要显示的强制类型转换。

union相比struct更加的节省空间。

3.2 案例二(很常用)

在嵌入式系统开发中,有时需要将一些变量存储在EEPROM中,变量类型若是char、int就很好办,可是如果要存储float、double类型的变量怎么办呢?
这个问题可以用共用体解决:

union myfloat
{
    char i[4];
    float j;
}Test;

因为float是四个字节,因此我们定义一个4个元素的char数组和float公用一段内存,接下来就是EEPROM存取了

在程序中要使用 j 的地方使用Test.j就行了,想把 j 写入EEPROM可以这样:

EEPROM_WRITE(0,myfloat.i[0]);
EEPROM_WRITE(1,myfloat.i[1]);
EEPROM_WRITE(2,myfloat.i[2]);
EEPROM_WRITE(3,myfloat.i[3]);

注:上面参数0、1、2、3为EEPROM地址,上面的EEPROM_WRITE只是示意,有时需要对地址使用(void*)进行类型转换

想把 j 从EEPROM读出可以这样:

myfloat.i[0]=EEPROM_READ(0);
myfloat.i[1]=EEPROM_READ(1);
myfloat.i[2]=EEPROM_READ(2);
myfloat.i[3]=EEPROM_READ(3);

然后在程序中继续使用Test.j就可以了。

4、寄存器的定义,实现整体的访问和单项的访问

struct register
{
	char a;
	char b;
	char c;
	char d;
};

union Register
{
   struct register;
   int whole;
};

这样就能实现单项和整体的访问,特别是引入位域操作等相关结构以后,能够实现每一个bit的访问。

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔的乌龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值