union作为C语言的一个关键字跟关键字volatile一样很少出现在程序员 的视野之中,当然相比于volatile,union的处境相对还好一点。但是我总觉得他是C语言的弃儿。
那么union与指针有什么关系呢?答案是有,我们都知道union的成员变量是共享同一块内存的,所以我们在使用union时会特别注意union在内存中的形态。与内存有关就与指针有关。
有的读者可能从开始学C语言就不觉的union有什么用,甚至有的读者学习和使用很长时间的C语言都从来没有使用过union。当然,几乎所以的应用在不使用union的情况下都可以实现。但是有时候使用它会有意想不到的效果。下面我主要列举union两方面的应用:
1.做嵌入式软件开发的读者都知道,我们几乎所有的通信方式传输的都是字节流,但是我们要传输的实际数据却各种各样,有float、double、int甚至是结构体。我们在传输之前往往需要将这些数据类型转换成字节流。以串口通信为例,假设单片机采集温度传感器的温度值为float型的数据,单片机采集到数据后需要把数据通过串口发送给上位机。这是我们遇到的问题是怎么把float的数据准确无误的转换为unsigned char型的数据,而上位机接收到数据后又怎样把unsigned char型的数据转换为float?
这时union就登上了历史的舞台,你可能有其他的转换方法但union无疑是最方便的。我们都知道float在内存中占4个字节,而unsigned char型的数据在内存中占1个字节。另外数据在内存中实际的存储形态都是二进制的01形态。而我们眼中的的float和unsigned char在内存眼里毫无区别。于是我们就用一个union作为一个转换器,输入float输出四个unsigned char,输入四个unsigned char输出一个float。废话少说代码如下:
union Converter
{
float Float;
unsigned char Uint[4];
};
下面我们来试试是不是可以转化:
#include <stdio.h>
union Converter
{
float Float;
unsigned char Uint[4];
};
int main()
{
union Converter var1, var2;
int i;
//下位机转化为unsigned char
var1.Float = 12.356;
printf("var1:%f\n", var1.Float);
//模拟串口传输过程
for (i = 0; i < 4; i++) {
var2.Uint[i] = var1.Uint[i];
}
//上位机接收到了数据
printf("var2:%f\n", var2.Float);
return 0;
}
上面的程序模拟了一次单片机向上位机传输一次数据,上位机接收数据的过程,运行结果如下图:
我们发现转化的过程完全就是简单的赋值过程,无需任何的多余操作。是不是发现了这个C语言弃儿的神奇之处了?
2.做单片机开发我们无法拒绝用户设备掉电后我们机器的运行参数不能丢失的要求。可是flash一般存储的都是unsinged int型数据,而我们设备的参数又是各种各样,有int,float,字符串甚至是结构体。几十个参数各不相同转化起来费时费力,怎么解决呢?
有了前面的例子你是不是已经想到啦?没错就是用神奇的union。
为了方便管理,我们先定义一个结构体,将所有我们需要存储的参数集合到一起。
struct storage
{
float tempure;
char name[20];
int flag;
};
然后我们计算一下这个结构体的大小, 4+20+4 = 28个字节。unsigned int数据占4个字节,所有我们的union定义如下:
union Converter
{
struct storage data;
unsigned int buff[7];
};
int main()
{
union Converter var1, var2;
var1.data.tempture = 12.35;
memcpy(var1.data.name, "wangxiaocheng", strlen("wangxiaocheng"));
var1.data.flag = 5;
//将var1写入flash
flashwrite(var1.buff, 7);
//延时5s
sleep(5);
//从flash中读出数据存入var2
flashread(var2.buff, 7);
printf("tempture:%f, name:%s, flag:%d\n", var2.data.tempture, var2.data.name, var2.data.flag);
return 0;
}
运行结果与第一个例子一样。我们发现我按照我前面两篇博文建立的内存模型,我们很好理解这种转化的内部原理。
没错我就是那个化腐朽为神奇的BLUCEJIE