目录
注:
本笔记参考B站up鹏哥C语言的视频
联合体类型的定义
联合也是一种特殊的自定义类型。
这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以联合也叫做共用体)。
比如:
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un_1;
//计算这个变量的大小
printf("%d\n", sizeof(un_1));
return 0;
}
打印结果:
为什么这里是4个字节呢?这就是联合体的特点。
联合的特点
||| 联合的成员是共用一块空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保证最大的那个成员)。
现在回来看之前的例子。
首先观察地址,打印:
printf("%p\n", &un_1); printf("%p\n", &(un_1.c)); printf("%p\n", (&un_1.i));
打印结果:
发现三个地址是一模一样的。
有
会发现,i 和 c 共用一块空间。
这就是共用体的一个特点:它的成员完全有可能共用了同一块空间。
联合体类型的初始化
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un_1 = { 10 };
return 0;
}
此时如果进行调试,看见:
此时 c 和 i 内存储的都是 10 。
那如果想要分别给 c 和 i 赋值要怎么办?
union Un un_1 = { 10 };
un_1.i = 1000;
un_1.c = 100;
在 i 内存储数字1000,实际上是在内存的4个字节内存储1000。而想在 c 内存储数字100,实际上是在内存的第一个字节内存储了100。
发现:既然 i 和 c 共用一个空间,所以在改动 i 的时候实际上也改动了 c 。同理,在改动 c 的时候也改动了 i 。这就是共用体的另一个特点:同一时间,只能使用共用体中的一个成员。
联合体的作用:让多个成员共同享有某一块空间。
例子:判断当前计算机的大小端存储
复习存储模式
大端存储模式、小端存储模式在存储到内存后,可以发现存在差异。
只需要拿出第一个字节的内容就可以找出不同,进而判断出计算机的大小端存储。
int main()
{
int a = 1;
if ((*(char*)&a) == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
函数实现
int check_sys()
{
int a = 1;
if ((*(char*)&a) == 1)
{
return 1;//小端
}
else
{
return 0;//大端
}
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
这里会发现,a 占了4个字节,而我们需要的,只是这4个字节中的第一个字节,这时候就可以使用联合体了。
------
union Un
{
char c;
int i;
};
如果给 i 赋值为1,再取出 c ,此时 c 就占据 i 的第一个字节。
联合体的写法:
int check_sys()
{
union U
{
char c;
int i;
}u;
u.i = 1;
return u.c;//此处是char类型,返回时转换成了int类型
//返回1,就是小端
//返回0,就是大端
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
联合体大小的计算
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
分析
union Un
{
char a[5];//占5个字节
int i;//占4个字节
};
int main()
{
union Un u;
printf("%d\n", sizeof(u));
return 0;
}
这里的打印结果是:
发现这里的打印结果并不是联合体最大成员的大小 5 ,而是 8 。
这是因为联合体也是存在对齐的:当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
- char a[5] 每个元素都是char类型,所以认为 a[5] 的对齐数就是 1 。
- int i 的对齐数就是 4 。
所以这些成员的最大对齐数就应该是 4 。
但是 a[5] 所占空间大小是 5 ,5 不是 4 的倍数,所以继续开辟空间,一直到开辟出第8个字节,此时 8 是 4 的倍数。
练习
union Un
{
char a[5];
char b;
};
可以猜测,这个联合体的大小是 5 。
union Un
{
short s[5];//10
int a;//4
};
一个short类型是2个字节,4 > 2,最大对齐数应该是4。
s[5] 所占空间大小是10,不是4的倍数,开辟到12个字节的大小。故联合体大小为:12 。