1.说明
union在C中本质上是一个结构体,用法和struct相似,定义如下:
union 名称
{
//... 成员
};
声明如下(要在名称前加上关键字union):
union 类型名称 变量名称;
调用如下(用expression.identifier的形式来调用成员):
a.member1 = 10; // a为union
p->member1 = 20; // p为union的指针
2.联合体union和struct的异同之处
union,意为联合体、共用体,而struct,意为结构体,作为特殊的数据结构类型,其相同之处在于:
共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。
不同之处在于:
结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;相应的,其缺点是struct内存空间的分配是粗放的,不管用不用,全分配,因此所占用的内存也相对较大。
而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”,同一时刻,只能为其定义的某一种数据类型分配内存,而不是为每一个数据成员配置空间;但优点是内存使用更为精细灵活,也节省了内存空间。
3.union的特点
在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,按最大需求开辟一段内存空间,并且所有的数据成员具有相同的起始地址(即固定首地址)。
4.大小端模式对union 类型数据的影响
下面看一个例子:
union
{
int i;
char a[2];
}*p, u;
p =&u;
p->a[0] = 0x39;
p->a[1] = 0x38;
p.i 的值应该为多少呢?
这里需要考虑存储模式:大端模式和小端模式。
- 大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
- 小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始。
那么,如何用程序确认当前系统的存储模式?写一个函数,若处理器是Big_endian ,返回0;若Little_endian ,则返回1。
先分析一下,按照上面关于大小端模式的定义,假设int 类型变量i 被初始化为1。
以大端模式存储,其内存布局如下图:
以小端模式存储,其内存布局如下图:
变量i 占4 个字节,但只有一个字节的值为1,另外三个字节的值都为0。如果取出低地址上的值为0,这是大端模式;如果取出低地址上的值为1,则是小端模式。既然如此,我们完全可以利用union 类型数据的特点:所有成员的起始地址一致来写目标函数:
int checkSystem( )
{
union check
{
int i;
char ch;
} c;
c.i = 1;
return (c.ch ==1);
}