一 联合体
1.定义
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
2.类型声明:
union Un{
int i;
char c;
};
注:每个成员之间仍是用分号隔开;联合体结束时不要忘加分号。
3.联合体变量的创建
union Un{
char c;
int i;
};
int main(){
//联合体变量的创建
union Un u1;
printf("%d\n",sizeof(u1));
return 0;
}
代码讲解:在联合体类型中,char c占1字节,int i 占4字节,通过上面对联合体类型的定义可知:联合体成员变量是共用同一块内存。所以char占用的字节是int i 的第一字节,如下图:
所以u1的答案为4字节 。
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联 合至少得有能力保存最大的那个成员)。
通过以上对于联合体的了解,我们发现联合体与结构体struct 有很多相似的地方。结构体相当于独立的房子,其中的每个成员变量都是相互独立的,不会相互影响其他变量;而联合体相当于大学宿舍,四个人、六个人共住一样。
1.练习
union Un
{
int i;
char c;
};
int main(){
union Un un;
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
printf("%p\n", &u2);
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
}
通过代码调试,我们发现,联合体本身大小和它的两个成员变量的地址都相同,更加具体的说明了联合体及其成员变量都是在同一地址开始使用内存 。
练习2.
union UN {
int i;
char j;
};
int main(){
union UN u2;
u2.i = 0x11223344;
u2.j = 0x55;
printf("%x\n", u2.i);
return 0;
}
解析:u2.j 是char型数据,将其赋值0x55,char型数据对于地址只能访问且修改一个字节
因为是联合体成员,共用内存,所以也间接修改了i的低位地址
0x11223344地址在VS中是以小端存储,为0x44 33 22 11(低地址向高地址)
所以char u2.j会优先访问修改低位地址44,赋值55,变为0x55 33 22 11(小端存储模式) 所以最后的结果:u2.的地址为0x11223355
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
这个就涉及到了内存对齐,联合体的内存对齐规则与结构体的内存对齐规则相同,大家不懂内存对齐规则的可以看一看这篇博客,里面详细的讲到了结构体内存对齐的规则与方式:
C语言结构体详解 (2) 结构体内存对齐,默认对齐数_
union Un1 {
char c[5];
int i;
};
union Un2 {
short c[7];
int i;
};
int main(){
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
请问两个printf输出的结果是什么?
第一个联合体Un1的大小为8字节
第二个联合体Un2的大小为16字节
代码解析:在联合体Un1中,成员变量1是char arr[5],虽然它是个数组,但它的对齐数是按照char型来计算的,所以char arr[5]的对齐数为1 ,指针从偏移量0开始,为第一个成员变量开辟五个字节内存,之后指针指向偏移量为5的地址,而int i是整型,它的对齐数是4,因为是联合体,int i会与char arr[5] 共用前4个字节,接下来偏移量5不是联合体最大对齐数4的整数倍,指针需要向后跳转,直到偏移量为8的地址才符合要求,所以Un1的大小为8字节。结构图如下:
代码解析2:在联合体Un2中,成员变量1仍然是个short型数组,成员变量1的对齐数为2,从偏移量0开始,向后开辟14个字节,之后指针指向偏移量为15的地址,int i因为联合体的原因与short数组共用前4个字节空间,此时,Int i 的对齐数4为联合体最大对齐数,偏移量15并不是4的整数倍,需要向后继续延申,直到偏移量16符合要求,所以联合体Un2的大小为16字节。
好了,以上就是我对联合体概念的讲解,大家觉得有用的话点个一键三连吧,谢谢!