目录
联合类型的定义
联合是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,这些成员会共用一块空间
//联合类型的声明,联合关键字union+联合类型Un
union Un 创建了Un类型
{
char a;
int i;
}u1; //创建了一个Un类型的变量u1
//u1是全局变量
int main()
{
union Un u2; //创建了一个Un类型的变量u2,u2是局部变量
return 0;
}
我们知道了如何定义一个联合体类型,现在我们来计算一下Un这个类型的联合体有多大
union Un
{
char a; //1字节
int i; //4字节
}u1; //sizeof(union Un)是多少呢?
答案是多少呢,我们来放到编译器中运行一下
你想到了吗?你可能会想char类型占1一个字节,int类型占4个字节,至少也得是5个字节吧?那么为什么呢?我们接着来看
我们惊讶的发现,三个地址竟然是一样的
为什么会这样呢,我们就需要说说联合的特点
联合的特点
联合的成员是共用一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
union Un
{
char a;
int i;
}u1;
这是一块内存空间,先存储char类型变量a(1个字节)
a |
我们由前面的图示可知u1.i的地址和u1.a的地址是一样的,因此这块内存空间接下来在存储int类型变量i(4个字节)时会变成如下
i | i | i | i |
我们发现a和i会共用一块空间,这就是为什么之前图片三者地址相同的原因,至于第一个计算联合体大小的问题,我放到了下一块内容进行描述
因为联合会共用一块空间,因此联合与结构体的初始化略有不同
结构体这样初始化,只会把变量a初始化为10,变量i为默认值0,但联合体就不一样了
因为联合体的成员会共用一块内存,会将所有的成员一同初始化
再看下段代码
u.i的赋值会覆盖掉对u.a的赋值(改a的时候i会改,改i的时候a又会改),因此联合的特点还有:同一时间只能使用它的一个变量
联合大小的计算
现在回归到我们一开始遗留的一个问题,到底如何计算联合体的大小
联合有自己的对齐方式
1.联合的大小至少是最大成员的大小
2.当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍
union Un
{
char a; //对齐数是1
int i; //对齐数是4
}; //最大对齐数是4
在Un类型的联合体中,最大成员的大小是4,而4正好又是最大对齐数的整数倍,因此sizeof(union Un)的结果就是4
我们在举两个例子
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
}; //sizeof(union Un1)和sizeof(union Un2)的结果是多少?
来看第一个
union Un1
{
char c[5]; //成员大小为5,对齐数为1
int i; //成员大小为4,对齐数是4
}; //最大对齐数是4
联合体大小至少是最大成员的大小5,但5不是最大对齐数4的整数倍,因此向上取到8,因此Un1类型的大小是8
第二个
union Un2
{
short c[7]; //成员大小是14,对齐数是2
int i; //成员大小是4,对齐数是4
}; //最大对齐数是4
联合体大小至少是最大成员的大小14,但14不是最大对齐数4的整数倍,因此向上取到16,因此Un2类型的大小是16