共用体
例子引入:
从中可得知,学生和老师的前四项信息相同,唯有第五项,学生是成绩,老师是教学科目。
如果采用传统结构体,会造成空间的浪费,比如学生采用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 }