共用体(Union)

共用体的定义格式为:

union 共用体名
{
成员列表
};

结构体和共用体的区别在于:

结构体的各个成员会占用不同的内存,互相之间没有影响;

而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。


结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。


例子:

union data {
int n;
char ch;
double m;
};
int main()
{
union data a;
printf("union 大小为:%d\n\n",sizeof(a));

a.n = 888;
printf(" %-10u, %-10c, %-10f\n", a.n, a.ch, a.m);
a.ch = '%';
printf(" %-10u, %-10c, %-10f\n", a.n, a.ch, a.m);
a.m = 6.66;
printf(" %-10u, %-11c, %-10f\n", a.n, a.ch, a.m);
printf("\n n 指向%p \n ch指向%p \n m 指向%p \n", &(a.n), &(a.ch), &(a.m));
}


输出为:

C语言编程基础(5)_共用体

我们可以观察到:

1)共用体的长度与共同体中最大数据类型(double)长度一致(都是8)

2)共同体中各个成员所在的地址相同


下面让我们来看内存的变化,为何会出现上面的结果

1)首先定义一个data型共同体a

C语言编程基础(5)_共用体_02

2)将int型改为888

C语言编程基础(5)_double_03

888转化为十六进制是0x0378,占用4个字节

0x78转化为十进制是120,查看ascii码,120位是小写x

0x0378转化为二进制是:

1100 1100 1100 1100 1100 1100 1100 1100 0000 0000 0000 0000 0000 0011 0111 1000

c c c c c c c c 0 0 0 0 0 3 7 8

C语言编程基础(5)_double_04

符号位位1,表明是负数

指数部分是100 1100 110 转化为十进制是614

尾数部分是0 1100 1100 1100 1100 1100 0000 0000 0000 0000 0000 0011 0111 1000


整数部分为011,转化为10进制为3,

小数部分为0.00 1100 1100 1100 1100 0000 0000 0000 0000 0000 0011 0111 1000

int xiaoshu[] = { 0,0,0 ,1,1,0,0, 1,1,0,0, 1,1,0,0, 1,1,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,1,1, 0,1,1,1 ,1,0,0,0};
int len = sizeof(xiaoshu) / sizeof(int);
double sum = 0;
for (int i = 0; i < len; i++)
{
sum += xiaoshu[i] * pow(0.5, i);
}
printf("\n小数部分为%.20f\n\n", sum);

C语言编程基础(5)_共用体_05

尾数部分为3.1999969482429762024366937112063169479370

3.2*2^614超出了计算范围


3)将char型改为%

C语言编程基础(5)_共用体_06

%对应的ascii码为37号,转化为二进制就是0x25

0x0325转化为十进制是805

4)最后将double型改为6.66

C语言编程基础(5)_double_07

十六进制为401A A3D7 0A3D 70A4,转化为二进制为:

100 0000 0001 1010 1010 0011 1101 0111 0000 1010 0011 1101 0111 0000 1010 0100

符号位位0,表明为正数

指数为0,表明不移动,正数部分为110,转化为十进制是6,

小数部分为0.10 1010 0011 1101 0111 0000 1010 0011 1101 0111 0000 1010 0100

转化为十进制

int xiaoshu[] = { 0,1,0, 1,0,1,0, 0,0,1,1, 1,1,0,1, 0,1,1,1 ,0,0,0,0, 1,0,1,0, 0,0,1,1, 1,1,0,1, 0,1,1,1, 0,0,0,0, 1,0,1,0, 0,1,0,0 };
int len = sizeof(xiaoshu) / sizeof(int);
double sum = 0;
for (int i = 0; i < len; i++)
{
sum += xiaoshu[i] * pow(0.5, i);
}
printf("\n\n小数部分为%20f\n\n", sum);

结果为:

C语言编程基础(5)_double_08

小数部分为0.66。

表示的double为6.66