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

来源:互联网 发布:用java编写爱心 编辑:程序博客网 时间:2024/04/30 05:59

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的访问。

0 0
原创粉丝点击