共用体是一种特殊的数据类型,允许您在 相同的内存位置存储 不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。这种方式在单片机中应用很多。
使用方式
定义共用体
union的定义方式如下:(超级类似struct的定义方式,使用方法都是一样的)
union [union tag]
{
member definition;
member definition;
...
member definition;
} [one or more union variables];
具体实例:
union Test{
char a[4];
int b;
};
定义共用体变量
和结构体类似有两种调用方式:
1. 定义共用体时直接定义
直接在定义的结构后边加上union变量名。如下:
union Test{
char a[4];
int b;
}test;
2. 在其他地方定义
和结构体的定义方式类似:
union Test test;
使用共用体成员
还是老说法,和结构体一样,使用“ . ”和“ -> ”对成员变量进行调用
int main(void){
union Test test;
union Test *test1 = test;
test.a[0] =10;
test1->a[1] = 1;
return 0;
}
内存结构
占用内存sizeof
由于共用体是所有的成员公用一个地址空间,所以共用体的内存空间应该要能保证所有的成员的数据能够正常的保存,这就形成的了一个木桶效应,应该要满足最大的成员的sizeof,并能够保证数据数据空间能够向该位取整(在没有比4大的数据类型则为向四取整)。
以下举几个例子进行分析:
例一:
union Test1
{
char a[2];
int b;
};
如上,数据类型的sizeof为2和4,最大的为4,所以进行向4取整,所以定义出的共用体变量的sizeof为4。
例二
union Test2
{
char a[9];
double b;
};
如上,数据类型的sizeof为9和8,最大的为9,由于有double数据类型存在,所以进行向8取整,所以定义出的共用体变量的sizeof为16。
例三
union Test3
{
char a[9];
double b;
int c[5];
};
如上,数据类型的sizeof为9、8和20,最大的为20,由于有double数据类型存在,所以进行向8取整,所以定义出的共用体变量的sizeof为24。
编译结果
以以下例子进行分析:
#include<stdio.h>
union Test1{
char a[9];
int b;
};
int main(void) {
union Test1 test1;
union Test1 *test = &test1;
test->b= 0;
test->a[0]= 10;
test->a[1]= 1;
printf("%d\n", sizeof(*test));
printf("%d\n", test->b);
return 0;
}
其中a[0] - 10 a[1] = 1。如果实在x86的平台下()。所以在b的一个八位存储着10,另一个个八位存储着1。这个时候就要牵扯到大小端的操作了。
一般来说x86下为大端存储,ARM下为小端存储。
下面以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value
Big-Endian: 低地址存放高位,如下:
高地址
---------------
buf[3] (0x78) – 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) – 高位
---------------
低地址
Little-Endian: 低地址存放低位,如下:
高地址
---------------
buf[3] (0x12) – 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) – 低位
--------------
低地址
虽然内存存储的不一样,但是结果是一样的(虚晃一枪)。为了方便分析,以所以在b的第一个八位存储着10,另一个个八位存储着1。
所以b = 10 + 2^8 =266