不常见的小知识-联合体
联合体(共用体)
联合类型的定义
联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员 共用一块内存空间(因此联合也叫共用体)
//联合类型的声明
union Un
{
char c;
int i ;
};
int main()
{
union Un un; // 联合变量的定义
printf("%d\n",sizeeof(un)); //4
}
定义时的注意事项:成员后面记得跟分号,{}后面也要有分号,union Un这一整个是联合体类型,不能直接使用Un定义变量,或者计算联合体大小
sizeof(Un) //err
sizeof(union Un) //正解
联合的特点
联合的成员共用一块内存空间,且都从起始位置开始存放,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
union Un
{
int i;
char c;
};
int main()
{
union Un un = {0};
printf("%p\n",&(un.i));
printf("%p\n",&(un.c));
printf("%p\n",&un);
}
打印结果相同地址相同。
成员都从第一个位置开始向后存放
结构体和联合体的区别
共同点:二者的访问方式,声明方式一样,且二者都有内存对齐
不同点:联合体的成员共用同一块空间 ,改变某一个成员,其他的都会发生改变,
而结构体的每个成员都有独立空间,互不影响
使用联合体判断大小端
大小端:二进制的字节序在内存中存放的顺序
int a = 1; //0x 00 00 00 01
// 低地址----->高地址
//小端存放:01 00 00 00 低字节内容放在低地址处
//大端存放:00 00 00 01
所以只要拿出第一个字节,判断是0还是1即可知道是小端还是大端
//法1:使用char*强转,只取第一个字节
int main()
{
int a = 1;
char* p =(char*)&a;
if(*p == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
优化:
int Check_DX()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = Check_DX();
if(ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
方法2:使用联合体
因为共用一块内存空间,所以可以给i赋值为1,只拿c中的内容即可
union U
{
char c;
int i ;
}u; //u为全局变量
int main()
{
u.i = 1;
if(u.c == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
写成函数形式:
int check_sys()
{
union
{
char c;
int i;
}u;
u.i = 1;
//返回1->小端
//返回0->大端
return u.c;
}
联合体大小的计算
-
联合体的大小至少是最大成员的大小
-
但最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍
(对齐数:成员类型的大小与编译器的对齐数(VS为8)比较,取较小值)
(最大对齐数:联合体中所有成员的对齐数的最大值)
联合体也存在内存对齐!!!
//例子1
union Un1
{
char c[5];
int i;
};
int main()
{
printf("%d\n",sizeof(union Un1)); //8
return 0;
}
c为5个元素的char类型数组,相当于存放了5个char类型的变量,c的大小为5字节, 但是char类型大小为1byte,所以对齐数为1
i为整形变量,大小为4bit,对齐数为4
Un1成员的最大对齐数为4,最大成员大小为5
但是5不是4的倍数,浪费3个字节->联合体Un1大小为8
//例子2
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%d\n",sizeof(union Un2)); //16
return 0;
}
c为7个元素的short类型数组,相当于存放了7个short类型的变量,c的大小为2*7=14字节, 但是short类型大小为为2byte 对齐数为2
i为整形变量,大小为4bit,对齐数为4
Un2成员的最大对齐数为4,最大成员大小为14,14不是4的倍数,所以浪费2个字节
->结构体Un2的大小为16byte
- 点赞
- 收藏
- 关注作者
评论(0)