🚠订阅专栏:自定义类型
🚜关注博主:翻斗花园第一代码手牛爷爷
🚙gitee仓库:牛爷爷爱写代码
🚗前言
这篇文章我们来介绍第三个自定义类型——联合体(共用体)。联合体也是一种特殊的自定义类型,这种类型的变量也包含一系列的成员,特征是这些成员共用同一块空间。因此也称共用体。
🚕联合体的声明
联合体的关键字是union
,联合体的声明与前两个自定义类型的声明有异曲同工之处。联合体的声明形式如下代码。
union num
{
int i;
char ch;
short t;
};
🚒联合体的定义
联合体的定义我们可以在声明时进行定义,如下代码。
union num
{
int i;
char ch;
short t;
}val2, val3;
也可以在函数中进行定义,如下代码。
union num
{
int i;
char ch;
short t;
};
int main()
{
union num val;
return 0;
}
🚑联合体详解
🚒详解一
联合体的成员公用一块空间,我们通过一段代码来观察,如下代码。
union num
{
int i;
char ch;
short t;
};
int main()
{
union num val;
printf("%d\n", sizeof(val));
printf("%d\n", sizeof(union num));
return 0;
}
我们通过sizeof
计算出这个联合体的大小,运行结果如下图。
我们现在来分析联合体成员共用一块空间到底是怎么来进行共用的。首先我们知道如果几个成员想要共用一块空间的话,那么这块空间就必须得足够放下这几个成员,所以就得取这几个成员中所占空间最大的成员的空间作为共用的空间。在上述代码中我们来看联合体成员,变量i
是int
类型,变量ch
是char
类型,变量t
是short
类型,在vs下我们知道int
类型占4个字节,char
类型占1个字节,short
类型占2个字节,所以这个联合体的大小就是4个字节。
🚚详解二
在知道了联合体的大小之后,我们又想,联合体成员在同一块空间中又是怎么存储的呢?下面我们用一段代码来观察分析,如下代码。
union num
{
int i;
char ch;
short t;
};
int main()
{
union num val = { 0 };
printf("%p\n", &val.ch);
printf("%p\n", &val.i);
printf("%p\n", &val.t);
return 0;
}
我们用%p
来打印各个成员的地址,运行结果如下图。
我们可以观察到,每个成员的起始地址都是一样的,证明他们共用了一块空间。在此基础上,我们画图来进行理解分析,如下图。
在理解联合体的存放机制后我们可以发现,当我们存放第一个数据进去的时候没什么影响,但是当我们存放第二个数据进去的时候,那么第一个数据就会改变。我们用代码来观察,如下代码。
union num
{
int i;
char ch;
short t;
};
int main()
{
union num val = { 0 };
val.i = 10;
printf("%d\n", val.i);
val.t = 1;
printf("%d\n", val.i);
return 0;
}
我们创建一个变量,然后将10赋值给i
,打印i
的值后在将1赋值t
,然后再打印i
的值,观察两次结果的变化,运行结果如下图所示。
我们可以观察到i
的值发生了变化,再次证明了联合体成员共用一块空间。
🚑详解三
前面我们说联合体的大小是最大成员的大小,这种说法其实是不完全正确的,正确的说法因该是联合体的大小至少是最大成员的大小,而且还有一条规则是当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。这里我们还是通过代码来进行观察,如下代码。
union num
{
int i;
char ch[5];
};
int main()
{
union num val = { 0 };
printf("%d\n", sizeof(union num));
return 0;
}
这个代码当我们不注意第二条规则的话,我们很容易就认为这个联合体的大小就是5,但是当我们结合第二天规则我们发现,联合体的成员的最大对齐数为4,而最大成员的大小为5,5不是4的整数倍,因此需要扩容到最大对齐数的整数倍,联合体的大小就为8。我们运行代码观察结果,如下图。
我们再画图进行分析,如下图。
其中黄色扩容出来的内存都是没有的内存。
🚐总结
更新到这,C语言自定义类型到这里又告一段落了,在文中如果有错误或者纰漏还望指正,欢迎评论区进行留言评论,如果觉得有帮助,希望大家支持一下,来个一键三连。