文章目录
Union
联合体是一种数据类型,表示在同一个内存空间中存储不同的数据类型,联合体有时也被称为共用体,联合体只能存储一个值
联合体主要设计用于一种表以存储无规律、事先也不知道的混合类型
Union定义格式
1、先定义、后创建变量
union test{
int num;
short sh;
char ch;
};
union test t1,t2,t3;
2、定义的同时创建变量
union test{
int num;
short sh;
char ch;
}t1,t2,t3;
Union初始化
1、初始化联合体第一个元素
#include <stdio.h>
union test{
int num;
short sh;
char ch;
};
int main()
{
union test t1 = {88};
printf("t1.num=%d\n",t1.num);
printf("t1.sh=%d\n",t1.sh);
printf("t1.ch=%d\n",t1.ch);
return 0;
}
2、联合体指定初始化
#include <stdio.h>
union test{
int num;
short sh;
char ch;
};
int main()
{
union test t1 = {.ch = 'A'};
printf("t1.num=%d\n",t1.num);
printf("t1.sh=%d\n",t1.sh);
printf("t1.ch=%d\n",t1.ch);
return 0;
}
3、联合体初始化同类别的联合
#include <stdio.h>
union test{
int num;
short sh;
char ch;
};
int main()
{
union test t2;
t2.sh = 20;
union test t1 = t2;
printf("t1.num=%d\n",t1.num);
printf("t1.sh=%d\n",t1.sh);
printf("t1.ch=%d\n",t1.ch);
return 0;
}
Union与Struct的区别
结构体的各个成员占用不同的内存,互相之间没有影响;联合体的所有成员都占用同一块内存,修改一个成员会影响其他成员
结构体占用的内存大于等于所有成员占用的内存的总和;联合体占用的内存等于其最大成员所占用的内存,联合体采用内存覆盖的技术,同一时刻只能保存一个成员的值,对联合体新成员赋值会将原来的值覆盖掉
Union的内存分布
union test{
unsigned int num;
short sh;
char ch;
};
上面三种初始化例子都是对联合体的单个成员进行单一赋值,联合体成员都是占用同一块内存,所以联合体每个成员输出的都是同一个值
1、先赋值char,再赋值short
#include <stdio.h>
union test{
unsigned int num;
short sh;
char ch;
};
int main()
{
union test t; //1000 ----> 11 1110 1000
//t.sh = 1000; //11101000 -----> 10010111 10011000 =- (2^4+2^3) =- (16+8) = -24
t.ch = 'a';
t.sh = 1000; // 1100001 1101100001
printf("t.num=%d\n",t.num);
printf("t.sh=%d\n",t.sh);
printf("t.ch=%d\n",t.ch);
return 0;
}
从运行结果可以看到联合体t1的三个成员num、sh、ch分别为1000、1000、-24
首先联合体t1三个成员都占用4个字节的内存空间,首先对char类型成员进行赋值:ch=‘a’,此时联合体三个成员输出都为字符a的编码值97,然后对short类型成员进行赋值:sh=1000;因为联合体同一时刻只能保存一个值,所以1000会将之前的字符编码值覆盖掉,1000的二进制数表示为:0000 0011 1110 1000;故此时联合体的num、sh成员输出为1000,而ch成员只占用一个字节,所以此时ch表示的是sh成员的一个字节内存上的二进制数,即:1110 1000,然后负数符号位不变,其余取反加1得到补码为:1001 1000,为-24
2、先赋值short、在赋值char
#include <stdio.h>
union test{
unsigned int num;
short sh;
char ch;
};
int main()
{
union test t; //1000 ----> 11 1110 1000
t.sh = 1000; //11101000 -----> 10010111 10011000 =- (2^4+2^3) =- (16+8) = -24
//t.ch = 'a';
printf("t.num=%d\n",t.num);
printf("t.sh=%d\n",t.sh);
printf("t.ch=%d\n",t.ch);
printf("*************\n");
t.ch = 'a'; // 1100001 1101100001
printf("t.num=%d\n",t.num);
printf("t.sh=%d\n",t.sh);
printf("t.ch=%d\n",t.ch);
return 0;
}
![联合体内存分布2](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211123/联合体内存分布2.5ndss4feols0.png)
从运行结果可以看到联合体t1的三个成员num、sh、ch分别为865、865、97
先赋值short类型:sh=1000,同上联合体三个成员输出分别为:1000、1000、-24
此时联合体所占用的四个字节的二进制数为0000 0011 1110 1000;然后赋值char类型:ch = ‘a’,此时ch占用第一个字节的二进制数会覆盖了之前sh在第一个字节所表示的二进制数,此时联合体占用的四个字节上的二进制数为0000 0011 0110 0001,所以此时输出联合体的ch成员时不会还是为字符编码值97,但是此时二进制数0000 0011 0110 0001转换成十进制为865
大端小端
计算通常采用的字节存储方式是两种:Big-Endian和Litter-Endian
字节序?
字节序:就是字节的顺序,大于一个字节类型的数据在内存中的存放顺序
Big-Endian:大端是高位字节先存储(低地址)
Litte-Endian:小端是低位字节先存储(低地址)
网络字节序:TCP/IP协议各层将字节序定义为Big-Endian,因此TCP/IP中使用的字节序被称之为网络字节序,也就是大端
操作系统一般都是小端
高低字节:不论什么进制,靠近左边的称之为高位字节,靠近右边为低位字节
**就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。**
Big-Endian:最不重要字节(LSB)存放在最低端的地址上
Litter-Endian:最不重要字节(LSB)存放在最低端的地址上
判断大小端
#include <stdio.h>
union endian
{
int a;
char ch;
};
int main()
{
union endian value;
value.a = 0x1234;
if (value.ch == 0x12)
printf("big endian\n");
else if (value.ch == 0x34)
printf("little endian\n");
}
总结
联合体是一种数据类型,表示在同一个内存空间中存储不同的数据类型,只能存储一个值,同一时刻只能保存一个成员的值,对联合体新成员赋值会将原来的值覆盖掉
赶紧学习起来吧!我是一个正在努力找回自我的人,希望能和一起学习的人成长,有错误的地方请各位大佬帮忙指正,如果觉得有帮助就点个赞当作对我的一个小肯定❤,peace&love