以前在学习C语言或C++的时候,只学习了一些常用的语法。对于一些少见的本着后面遇到了再来学的目的,就没有去学习过。
今天早上看群里面有人问,float怎么转换为4个字节。我一想,这不是我以前做协议解析时候的问题吗,当时我是用指针强制转换的方法去实现的。方法就像下面那代码片段一样。
//转换float数据到字节数组
unsigned char i;
float floatVariable;
unsigned char charArray[4];
(unsigned char) *pdata = ((unsigned char)*)&floatVariable; //把float类型的指针强制转换为unsigned char型
for(i=0;i<4;i++)
{
charArray[i] = *pdata++;//把相应地址中的数据保存到unsigned char数组中
}
//转换字节数组到float数据
float floatVariable;
unsigned char i;
void *pf;
pf = &floatVariable;
(unsigned char) * px = charArray;
for(i=0;i<4;i++)
{
*(((unsigned char)*)pf+i)=*(px+i);
}
过了一会儿,另一个人在群里说了,联合体的方法非常好用。当然好学的我,又要问了,什么是联合体,什么是union。一段时间过去了,并没有人回我(可能是因为太早了,今天早上醒的比较早,看群也比较早)。奈何没人给我讲啊,我就只有自己去百度了。
下面开始正文,上面全是白扯。。。
union 叫共用体,又叫联合、联合体。“联合体”是一种特殊的类,也是一种构造类型的数据结构。在一个“联合体”内能够定义多种不同的数据类型。一个被说明为该“联合体”类型的变量中。同意装入该“联合体”所定义的不论什么一种数据。这些数据共享同一段内存,以达到节省空间的目的。
说了这么多,到底什么是联合体呢,就是在这个数据结构内,会有多种不同的数据,这些数据共同拥有同一段内存。。。好吧,可能感觉还不是很懂。看下面的代码片段,你可能就懂了。
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}RGB_Typedef;
typedef union
{
RGB_Typedef rgb;
unsigned int value;
}Pix_Typedef;
这就声明了一个结构体和一个联合体,联合体内部包含了一个结构体和一个无符号整形数据(32位的)。刚刚我们说了联合体内部的数据共享同一段内存,意思就是说联合体内部的结构体的首地址和无符号整形数据的首地址是相同的,不信?你看下面的片段。
#include "stdio.h"
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}RGB_Typedef;
typedef union
{
RGB_Typedef rgb;
unsigned int value;
}Pix_Typedef;
void main()
{
Pix_Typedef pix;
printf("%x\r\n",&pix.rgb);
printf("%x\r\n",&pix.value);
}
运行结果截图:
可以清晰的看到,联合体里面的结构体和无符号整形数据是相同的。
我们知道了联合体的功能了,那么到底会有一些怎么样的应用呢?
我们都知道RGB三原色是有红、绿、蓝各占一个字节(0-255)表示的,有些时候,我们需要单独去R、G、B三个色值,有些时候,又需要合在一起使用。难道我们每一次使用的时候,都对数据进行拆分、融合?这样实在是太麻烦了。我们就可以利用联合体的方式来定义三原色。
声明一个结构体包含三原色,然后在声明一个联合体包含前一个结构体和三原色融合的数值。如下图所示。
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}RGB_Typedef;
typedef union
{
RGB_Typedef rgb;
unsigned int value;
}Pix_Typedef;
如果我们定义三原色分别为0X11、0X22、0X33,然后不再做任何处理,直接打印value。会是怎么一种情况。代码如下
#include "stdio.h"
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}RGB_Typedef;
typedef union
{
RGB_Typedef rgb;
unsigned int value;
}Pix_Typedef;
void main()
{
Pix_Typedef pix;
pix.rgb.Blue=0X33;
pix.rgb.Green=0X22;
pix.rgb.Red=0X11;
printf("%X\r\n",pix.value);
}
运行结果如下图:
这里需要说明一下的是,unsigned int 是一个4字节数据,而前面我们只定义了三个unsigned char ,只占三个字节。所以MSB自动补齐了。在union中,分配内存空间的大小,等于占内存最大的数据类型字节大小。
在上面,我们已经看到可以直接通过定义R、G、B值,来修改融合后的值。当然,反过来也是可以的。我们首先对value赋值,然后再输出R、G、B值。代码如下:
#include "stdio.h"
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}RGB_Typedef;
typedef union
{
RGB_Typedef rgb;
unsigned int value;
}Pix_Typedef;
void main()
{
Pix_Typedef pix;
pix.value = 0X00123456;
printf("%X\r\n",pix.rgb.Red);
printf("%X\r\n",pix.rgb.Green);
printf("%X\r\n",pix.rgb.Blue);
}
运行结果如下图:
由此,可以说明,无论是修改结构体,还是修改unsigned int ,都会对对方造成影响。因为他们是共享同一段内存。
上面讲了union在三原色中的应用,现在我们继续来讲如何利用union来做flaot 和 Byte 之间的转换。
首先在union当初定义一个unsigned char 类型的数组,元素为4个,在定义一个float 类型数据。然后再对数组中的每一个元素进行赋值,最后直接打印float数据。代码如下:
#include "stdio.h"
typedef union
{
unsigned char Byte[4];
float Float;
}Float_Byte;
void main()
{
Float_Byte fb;
fb.Byte[0] = 0x00;
fb.Byte[1] = 0x00;
fb.Byte[2] = 0x48;
fb.Byte[3] = 0x42;
printf("%f\r\n",fb.Float);
}
运行结果如图:
由此可见,用union来做float与Byte转换时完全可行,甚至简单的。只需要注意好内存对齐。
由Byte转换为float已经推荐给大家了,至于float转Byte大家可以自己想想。
有点累了,今天起的太早,睡个午觉。。。。。。
如有不足之处或者是更好的处理建议,请与作者联系。QQ:945116700 邮箱 :duo_lin0119@163.com
谢谢各位的阅读