使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。
共用体定义:
union 共用体名
{
成员表名
}变量表名
例:
/*先声明类型再定义*/
union student
{
int num;
char name;
float score;
}xiaowang;
/*直接定义*/
union
{
int num;
char name;
float score;
}xiaowang;
结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有其自己的内存单元。
公用体变量所占内存长度是等于最长的成员长度。
上面的例子所占长度是各占4个字节 (实型变量占4个字节)而不是2+1+4=7个字节
一些书中把公用体也叫 -> "联合"
注意特点:
1.同一内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是其中几种。
2.共用体变量起作用的成员是最后一次存放的成员,再存入一个新的成员后,原有成员失去作用,如:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union
{
int num;
char name[20];
float score;
}xiaowang;
main()
{
xiaowang.num=1;
strcpy(xiaowang.name,"xiaowang");
xiaowang.score = 88;
printf("%d",xiaowang.num);
/*此时xiaowang.num已经失去了意义*/
}
3.共用体变量的地址和各成员变量的地址都是同一地址
4.不能用共用体变量名赋值,也不能引用变量名来得到一个值,又不能在定义共用体变量时对它初始化
5.不能把共用体变量作为参数,也不能使函数返回时带有共用体,但可以使用指向共用体变量的指针(与结构体用法相似)
6。共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体类型也可以出现在共用体类型定义中,数组也可以作为共用体成员。
一组数据:有老师、学生。数据包括:学号、姓名、性别、职业、班级/职务
如果职业是s第5项就是班级,如果是t第5项就是职务:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct
{
int num;
char name[20];
char sex;
char job;
union
{
int classes;
char position[20];
}category;
}person[2];
main()
{
int i;
for(i=0;i<2;i++)
{
scanf("%d %s %c %c ",&person[i].num,person[i].name,&person[i].sex,&person[i].job);
if(person[i].job=='s')
{
scanf("%d",&person[i].category.classes);
}
else if(person[i].job=='t')
{
scanf("%s",&person[i].category.position);
}
else
{
printf("input error!");
}
}
printf("
");
printf("No Name sex Job class/position
");
for(i=0;i<2;i++)
{
if(person[i].job=='t')
{
printf("%-6d%-10s%-8c%-6c%-s
",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);
}
else
{ printf("%-6d%-10s%-8c%-6c%-d
",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.classes);
}
}
}
可以看出在结构体类型声明中包括了共用体类型,category是结构体成员中的一个成员名,在共用体中成员为class、position,前者为整型,后者为字符数组(存放"职务"的值--字符串).
枚举类型:
如果一个变量只有几种可能的值,可以定义为枚举类型。所谓枚举是指将变量的值一一列举出来,变量的值,只限于列举出来的值的范围内。
声明:
enum weekday(sun,mon,tue,wed,thu,fri,sat);
声明一个枚举类型enum weekday,可以用此来定义变量如:
enum weekday workday,week_end
workday和week_end被定义为枚举变量,它们的值只能是sun到sat之一。例如:
workday=mon;
week_day=sun;
直接定义:
enum{sun,mon,tur,wed,thu,fri,sat} workday,week_end;
其中sun,mon等称为枚举常量,是用户自定义的标识符
1.枚举元素按常量处理,他们不是变量,不能对它们赋值。
2.枚举元素作为常量,他们是有值的编译按定义时的顺序使他们的值为0,1,2。。。
例:口袋中有红、黄、蓝、白、黑5种颜色球若干个。每次从口袋中取出3个球,问得到3种不同色的球可能的取法,打印出3种颜色:
#include <stdio.h>
main()
{
enum color{
red,yellow,blue,white,black
};
enum color i,j,k,pri;
int n,loop;
n=0;
for(i=red;i<=black;i++)
{
for(j=red;j<=black;j++)
{
if(i!=j)
{
for(k=red;k<=black;k++)
{
if(k!=i&&k!=j)
{
n=n+1;
printf("%d: ",n);
for(loop=1;loop<=3;loop++)
{
switch(loop)
{
case 1:pri=i;break;
case 2:pri=j;break;
case 3:pri=k;break;
default:break;
}
switch(pri)
{
case red:printf("%s ","red");break;
case yellow:printf("%s ","yellow");break;
case blue:printf("%s ","blue");break;
case white:printf("%s ","white");break;
case black:printf("%s ","black");break;
default:break;
}
}
printf("
");
}
}
}
}
}
}
用typedef定义类型:
除了使用标准类型int、char、float、double、long等和自己声明的结构体、共用体、指针、枚举类型外,可以用typeof声明新的类型来代替已有的类型,如:
#include<stdio.h>
void main()
{
typedef int INTEGER;
typedef float REAL;
int a=3;
float b=3.45;
INTEGER c = 4;
REAL d = 4.54;
printf("a:%d,c:%d
",a,c);
printf("b:%.2f,d:%.2f
",b,d);
}
他们是等价的。
#include<stdio.h>
void main()
{
typedef struct
{
int year;
int mouth;
int day;
}DATE;
DATE birthday; /*声明一个DATE类型的生日*/
DATE *p /*p为指向结构体类型数据的指针*/
}
typedef int NUM[100];
NUM n;/*定义n为整型数组变量*/
typedef int *STR;/*声明STR为字符指针类型*/
STR p,s[10];/*p为字符指针变量,s为指针数组*/
typedef int (*POINTER)();/*声明POINTER为指向函数的指针类型,函数返回整型值*/
POINTER p1,p2; /*p1,p2为POINTER类型的指针变量*/
归纳:
1.先按定义变量的方法写出定义体。
2.将变量名换成新类型名。
3.在最前面加typedef。
4.然后用新类型名定义变量。
以数组为例说明:
1.int n[100]
2.int NUM[100]
3.typefef int NUM[100]
4.NUM arr;
以字符指针说明:
1.char *p
2.char *STR
3.typedef char *STR
4.STR p,s[10];
说明:
1.用typedef可以声明各种类型名,但不能用来定义变量。
int a[10],b[10],c[10];
都是一堆数组大小也相同,,可将数组类型声明为一个类型
typedef int ARR[10];
然后用ARR去定义数组变量。
ARR a,b,c;
2.用typedef只是对已存在的类型增加一个类型名,而没有创造新的。
像typedef int NUM[100] 无非是把原来用int n[10]定义的数组变量类型用一个新的名字NUM表示出来。
3.typedef与#define有相似之处
typedef int COUNT
#define COUNT int
作用都是用COUNT代表int,但事实上两者是不同的。
#define 是在预编译时处理的,只能做简单的字符串替换
typedef 是在编译时处理的,并不是做简单的字符串替换,例如:
typedef int NUM[10] 并不是去代替int,而是如同定义变量的方法声明一个类型
4.当不同源文件中用到同一数据类型(尤其是像定义数组、指针、结构体、共用体)等类型,常用typedef声明一些数据类型,单独放在一个文件中,需要用时导包
5.使用typedef有利于程序段通用与移植