共用体

例子引入:

 

 

 

 从中可得知,学生和老师的前四项信息相同,唯有第五项,学生是成绩,老师是教学科目。

如果采用传统结构体,会造成空间的浪费,比如学生采用score,但是course也会占用相应的字节(尽管不调用,但是占了内存空间)

若定义两个结构体分别保存学生和老师的信息,一旦数据多起来,就会有多个结构体类型,不便于管理。

 

 此时我们就要使用共用体:


介绍:

 

 快速入门:

1.定义共用体类型和共用体变量的三类方法

 

 实例演示:

 1 #include <stdio.h>
 2 
 3 union data{ //data是一个共用体,包含三个成员
 4     int n;
 5     char ch;
 6     short m;
 7 };  //理论上,n占4个字节,ch占1个字节,short占2个字节,理论上应为7字节,但是下面输出变量a的大小和int相同,为4个字节
 8 //他们共有数据空间,而该空间的大小以占用最大的成员为准(此处为4字节)
 9 
10 void main(){
11     union data a;   //定义一个共用体变量a
12     printf("%d,%d\n", sizeof(a), sizeof(union data));   //4,4
13     a.n = 0x40;
14     printf("%d,%c,%d\n", a.n, a.ch, a.m);
15     a.ch = '9';
16     printf("%d,%c,%d\n", a.n, a.ch, a.m);
17     a.m = 0x2059;
18     printf("%d,%c,%d\n", a.n, a.ch, a.m);
19     a.n = 0x3E25AD54;
20     printf("%d,%c,%d\n", a.n, a.ch, a.m);
21 }

输出为:

 

 内存布局:

首先要理解,数据保存都是从最低为开始(即右边绿色箭头处为最低位)

关于第一个a.n = 0x40;

内存中是这样定义的:

 

 而输出要求我们轮流打印a.n,a.ch,a.m,则把这个值(十进制为64),轮流按规定输出

比如第一个要求%d,则输出64,第三个同理输出64,而第二个要求%c,则对应ASII码,找到为64的字符(为:@),并将它输出

关于第二个a.ch = '9';

内存中是这样的:

首先,字符9,ASII为0011 1001,在内存中,为:

 

 输出同理,但是注意这个9是字符的9不是数字9

关于第三个a.m = 0x2059;

先转为二进制表示,为:

2  0  5  9

0010 0000 0101 1001

此时它占用两个字节,内存图如下:

 

 按%d输出就为8281,按%c输出则(注意,char只占一个字节,所以它只看0101 1001这部分输出,上面由于均只占用一个字节,因此不做区分,这里要额外留意!!!)把0101 1001转为ASII(89),找到相应字符即可。

关于第四个a.n = 0x3E25AD54;

转为二进制为:

3  E  2  5  A  D  5  4

0011.1110.0010.0101.1010.1101.0101.0100

此时有32位数共4字节,此时内存图为:

 

 按上面规律输出

首先是int类型的%d输出,int占四个字节,因此他会完整的把四个字节的内容转化为十进制输出:1,042,656,596

接着按char类型的%c输出,char占一个字节,所以它只输出最低位的字节(最右边),转化为ASII,输出字符:T

最后按short类型的%d输出,short占两个字节,所以它只输出从右往左的两个字节(即1010 1101 0101 0100),为:

 


实例应用:

 

 1 #include <stdio.h>
 2 
 3 #define TOTAL 2     //定义下面结构体数组有多少个人
 4 
 5 //也可以用以下类型来定义,记得要把结构体内的的注释掉
 6 /*
 7 union MYUNION{
 8     float score;
 9     char course[20];
10 }
11 */
12 
13 //定义了一个结构体Person
14 struct Person{
15     char name[20];  //name
16     int num;    //编号
17     char sex;   //性别 f=>女 m=>男
18     char profession;    //职员 s=>学生 t=>老师
19     union{
20         float score;
21         char course[20];
22     }sc;    //sc是一个共用体变量
23     //union MYUNION sc; //配套最上面使用
24 };
25 
26 void main(){
27     int i;
28     struct Person persons[TOTAL];   //定义了一个结构体数组
29     //输入人员信息
30     for( i = 0; i < TOTAL; i++){
31         printf("Input info:");
32         scanf("%s %d %c %c", persons[i].name, &(persons[i].num), &(persons[i].sex), &(persons[i].profession));
33         if (persons[i].profession == 's'){
34             printf("请输入学生的成绩:");
35             scanf("%f", &persons[i].sc.score);  //如果是学生
36         }else{
37             printf("请输入老师的任课:");
38             scanf("%s", &persons[i].sc.course); //如果是老师
39         }
40         fflush(stdin);  //刷新输入
41     }
42     //输出人员信息
43     printf("\nName\t\tNum\tSex\tProfession\tScore/Course\n");
44     for( i = 0; i < TOTAL; i++){
45         if(persons[i].profession == 's'){
46             printf("%s\t\t%d\t%c\t%c\t\t%f\n", persons[i].name, persons[i].num, persons[i].sex, persons[i].profession, persons[i].sc.score);
47         }else{
48             printf("%s\t\t%d\t%c\t%c\t\t%s\n", persons[i].name, persons[i].num, persons[i].sex, persons[i].profession, persons[i].sc.course);
49         }
50     }
51 }

 

posted @ 2022-10-19 17:58  Morning枫  阅读(68)  评论(0编辑  收藏  举报