第10章结构体、枚举和共用体类型.ppt
第8章 结构体、枚举和共用体类型,10.1 结构体类型10.2结构体和函数10.3 动态数据结构链表10.4枚举类型10.5共用体类型10.6 用户自定义类型,10.1 结构体类型,结构体类型的定义结构体类型中可以根据需要包含若干相同或不同类型的成员,这些成员所代表的信息必须是相关的信息。结构体类型定义的格式为:struct 结构体名类型名 成员名1;类型名 成员名2;类型名 成员名n;;例如,struct date int year;int month;int day;,10.1 结构体类型,struct studentint number;/*学号*/char name8;/*姓名*/char sex;/*性别*/float score4;/*成绩*/;struct是结构体类型的标识,是关键字。struct和后面的结构体名共同构成结构体类型名。结构体名应符合标识符的命名规则。结构体所有成员的定义用花括弧括起来。结构体成员的定义方式和变量的定义方式一样,成员类型可以是基本类型的,也可以是构造类型的。各成员之间用分号分隔。结构体内的各个成员名不能重名,但成员名可以与结构体外其他标识符同名,并不产生冲突。,10.1 结构体类型,结构体变量的定义用已经定义的结构体类型定义结构体变量。struct student stu;定义结构体类型的同时定义结构体变量。stu1,stu2。struct student int number;/*学号*/char name8;/*姓名*/char sex;/*性别*/float score4;/*成绩*/stu1,stu2;,10.1 结构体类型,定义无名结构体类型的同时定义结构体变量。这种定义形式省略了结构体名。不再需要定义此种类型变量的情况才可采用这种方式。struct int number;/*学号*/char name8;/*姓名*/char sex;/*性别*/float score4;/*成绩*/stu结构体变量各个成员按照定义的顺序依次占用连续的空间。可以定义指针变量指向结构体类型变量。结构体变量的地址虽与其第一个成员的地址的值是相同的,但它们的类型是不同的。它们之间不能直接相互赋值,但是可以先将其用强制类型转换,转换为同一类型指针后相互赋值。,10.1 结构体类型,结构体变量的初始化和引用结构体变量的初始化若在定义之后进行初始化操作,只能对每个成员单独进行赋值。若在定义变量的同时进行初始化,则用一对花括弧括起各个成员值的列表并用赋值号和变量连接,成员值之间逗号分隔,具体格式为:结构体类型名 结构体变量=成员值列表;例如,struct student stu=1001,wang,f,60.5,80,75,90;结构体变量的引用只能引用结构体变量的成员,不能引用整个结构体变量。结构体变量的成员引用形式为:结构体变量名.成员名其中“.”称为成员运算符。如果是通过指向结构体变量的指针引用结构体成员,形式为:(*指针变量名).成员名 或 指针变量名-成员名,10.1 结构体类型,如果结构体的成员仍然是构造类型,则需要逐级引用,直至最低级的成员,即只能对结构体变量最低级的成员进行存取和运算。【例10.1】输入学生的各项信息,计算总分和平均成绩后输出。#include stdio.hstruct dateint year;int month;int day;/*定义结构体类型struct date*/struct studentint number;/*学号*/char name10;/*姓名*/struct date birthday;/*生日,struct date类型*/,10.1 结构体类型,float score4;/*四门课成绩*/float total;/*总分*/float ave;/*平均成绩*/;/*定义结构体类型struct student*/main()struct student stu,*p;int k;printf(please enter number,10.1 结构体类型,for(stu.total=0,k=0;knumber);printf(name:%sn,p-name);printf(birthday:%d,%d,%dn,(*p).birthday.year,(*p).birthday.month,(*p).birthday.day);printf(score:);for(k=0;kscorek);printf(ntotal:%6.2f n,stu.total);,10.1 结构体类型,printf(average:%6.2f n,stu.ave);某次程序运行结果为:please enter number&name:1002 liplease enter birthday(year,month,day):1975 6 8please enter the score(4):80 78.5 92 83.5number:1002name:libirthday:1975,6,8score:80.00 78.50 92.00 83.50total:334.00average:83.50,10.1 结构体类型,结构体数组结构体数组的定义、初始化若数组元素的类型为结构体类型,数组为结构体数组。定义结构体数组的同时也可对数组进行初始化操作。例如,struct studentint number;/*学号*/char name10;/*姓名*/float score4;/*四门课程成绩*/float total;/*总分*/float ave;/*平均成绩*/stu3=461,liu,80,78,67,80,0,0,032,geng,98,78,86,90,0,0,103,qian,79,89,68,80,0,0;可以定义指向结构体数组元素的指针变量,然后通过指针对数组元素操作。,10.1 结构体类型,结构体数组的引用结构体数组元素也是通过数组名和下标来引用,但要注意只能对最低级的成员进行存取和运算。引用的一般形式为:数组名下标.成员名例如,stu1.number、stu0.score2、stu2.ave通过指针引用结构体数组元素的形式和通过指针引用结构变量形式一样,为:(*指针变量名).成员名 或 指针变量名-成员名 例如,语句“p=,10.1 结构体类型,【例10.2】计算某班期末考试中所有学生的总分和平均成绩。#define N 50#include stdio.hstruct studentint number;/*学号*/char name10;/*姓名*/float score4;/*四门课程成绩*/float total;/*总分*/float ave;/*平均成绩*/;main()struct student stuN,*p;int i,k;for(i=0,p=stu;pstu+N;p+,i+)/*输入学生的信息*/printf(the%d studentn,i);printf(number,10.1 结构体类型,scanf(%d%s,10.2结构体和函数,结构体变量的成员作为函数参数结构体变量的成员可作为函数的实际参数,但是不适合作函数的形式参数。结构体变量的成员作函数实参的用法与普通变量作函数实参的用法相同,形参与实参之间仍然是“值传递”的方式。【例10.3】重新编写例10.2。#define N 50#include stdio.hstruct studentint number;/*学号*/char name10;/*姓名*/float score4;/*四门课程成绩*/float total;/*总分*/float ave;/*平均成绩*/;,10.2结构体和函数,float total(float s,int n)/*计算总成绩*/int k;float sum=0;for(k=0;kn;k+)sum+=sk;return(sum);float average(float x,int n)return(x/n);/*返回平均值*/main()struct student stuN;int i,k;for(i=0;iN;i+)/*输入学生的信息*/printf(the%d studentn,i);printf(number,10.2结构体和函数,scanf(%d%s,10.2结构体和函数,结构体指针变量作为函数参数允许函数之间传递结构体变量,若形参是结构体变量,那么实参也应是同类型的结构体。被调用函数对形参结构体变量的修改不能传递给实参。形参结构体变量占用内存空间、接收实参数据带来空间和时间的巨大开销。因此语法上虽然允许,但一般很少采用这种方式。若向函数传递结构体变量的地址,则可以通过指针对实参结构体变量的空间操作,从而改变实参的值。参数传递时只需传递一个地址,空间和时间的代价都很小。一般采用结构体指针作为函数参数,而不采用结构体变量作为函数参数。,10.2结构体和函数,【例10.4】重新编写例10.3。#define N 50#include stdio.hstruct studentint number;/*学号*/char name10;/*姓名*/float score4;/*四门课程成绩*/float total;/*总分*/float ave;/*平均成绩*/;void input(struct student*stu)/*输入学生信息*/int k;printf(number,10.2结构体和函数,for(k=0;kscorek);void total_average(struct student*stu)/*计算总成绩和平均值*/int k;stu-total=0;for(k=0;ktotal+=stu-scorek;stu-ave=stu-total/4;void output(struct student*stu)/*输出学生信息*/int k;printf(number:%6dn,stu-number);printf(name:%sn,stu-name);printf(score:);,10.2结构体和函数,for(k=0;kscorek);printf(ntotal=%10.2f average=%10.2f n,stu-total,stu-ave);main()struct student stuN,*p;int i;for(i=0;iN;i+)/*输入学生的信息*/printf(the%d studentn,i);input(,10.2结构体和函数,结构体数组作函数参数向函数传递结构体数组实际也是传递数组的首地址。形参数组与实参数组使用共同的内存单元。函数形参、实数是同类型的结构体数组名或结构体指针。【例10.5】重新编写例10.4。#define N 50#include stdio.hstruct studentint number;/*学号*/char name10;/*姓名*/float score4;/*四门课程成绩*/float total;/*总分*/float ave;/*平均成绩*/;,10.2结构体和函数,void input(struct student stu,int n)/*输入学生的信息*/int i,k;for(i=0;in;i+)printf(the%d studentn,i);printf(number,10.2结构体和函数,for(;stutotal=0;for(k=0;ktotal+=stu-scorek;stu-ave=stu-total/4;void output(struct student*stu,int n)/*输出处理后的学生信息*/int k,i;for(i=0;inumber);printf(name:%sn,(stu+i)-name);printf(score:);,10.2结构体和函数,for(k=0;kscorek);printf(ntotal=%10.2f average=%10.2f n,(stu+i)-total,(stu+i)-ave);main()struct student stuN;struct student*q=stu;input(q,N);total_average(stu,N);output(stu,N);,10.3 动态数据结构链表,内存空间的动态分配和释放free函数free函数的的格式:void free(void*p);free函数的功能:释放指针变量p所指向的内存区,该函数没有返回值。一般p的值是调用malloc函数或calloc函数的返回值。malloc函数malloc函数的格式:void*malloc(unsigned int size);malloc函数的功能:在内存的动态存储区中分配size个字节的连续空间,并返回分配空间的起始地址。若分配失败,则返回空指针。注意:malloc函数的返回值一般是空类型的指针(有的编译系统将其处理成char类型的指针)。使用该函数时通常需要用强制类型转换,将其转换为所需要的类型。,10.3 动态数据结构链表,【例10.6】注意内存空间的分配和释放。main()double*pointer;pointer=(double*)malloc(sizeof(double);/*申请一个double类型变量所需内存空间*/*pointer=8.234;printf(“%6.4fn”,*pointer);*pointer=*pointer+10;printf(%7.4fn,*pointer);*pointer=*pointer/2;printf(%6.4f,*pointer);free(pointer);/*释放空间*/,10.3 动态数据结构链表,程序运行结果为:8.234018.23409.1170calloc函数calloc函数的的格式:void*calloc(unsigned int n,unsigned int size);calloc函数的功能:分配内存的动态存储区中n个长度为size个字节的连续空间,并返回分配空间的起始地址。若分配失败,则返回一个空指针。对calloc的返回值同样也可进行强制类型转换后使用。注意:calloc函数常用来为一维数组分配空间,其中n表示数组的长度,size表示数组元素所占字节数。这种方式获得的数组一般称为动态数组。,10.3 动态数据结构链表,【例10.7】注意内存空间的分配和释放。main()int*a,i;a=(int*)calloc(5,sizeof(int);/*申请5个整型变量所需内存空间*/for(i=0;i5;i+)*(a+i)=i+1;for(i=0;i5;i+)printf(%4d,*(a+i);free(a);/*释放空间*/程序运行结果为:1 2 3 4 5,10.3 动态数据结构链表,链表链表由若干个结点构成。一个结点就是一个结构类型的变量。链表的每个结点需要占用连续内存空间,但是整个链表无须占用连续空间。因此,结点成员应该包括两部分:一部分存放实际需要的数据信息,称为数据域;一部分存放指针,用来链接各个结点,称为链接域或指针域。在链表中,一个结点后面相邻的结点称为该结点的后继结点,该结点则称为其后继结点的前驱结点。单链表:结点指针域只包含一个后继结点地址的链表。用一个指针变量保存单链表的首地址,即第一个结点的地址,这个指针变量被称为头指针。头指针是一个链表的标志。注意:在链表的定义中,指向前驱结点或后继结点的指针的基类型是结点自身类型。,【例10.8】通过给结点的指针域赋值建立一个单链表。#include stdio.hstruct node char c;struct node*next;main()struct node*n1,*n2,*n3,*head,*p;/*申请三个结点空间*/n1=(struct node*)malloc(sizeof(struct node);n2=(struct node*)malloc(sizeof(struct node);n3=(struct node*)malloc(sizeof(struct node);/*建立链表*/head=n1;,10.3 动态数据结构链表,10.3 动态数据结构链表,n1-c=A;n1-next=n2;n2-c=B;n2-next=n3;n3-c=C;n3-next=NULL;for(p=head;p!=NULL;p=p-next)printf(%3c,p-c);,10.3 动态数据结构链表,链表的基本操作 为了简化链表的各种操作,一般在含有有效信息的所有结点之前再附加一个数据域不包含任何信息的结点。这个结点被称为“头结点”。头结点的存在是以一个结点空间为代价换取程序编写的简单明了。下面的各项链表操作都是针对有头结点的链表编写的,结点的类型均为:struct nodeint data;struct node*next;并假定成员data的值不可能为负数。,10.3 动态数据结构链表,创建链表采用从表尾插入新结点的方式,则创建链表的主要步骤为:生成只含有头结点的空链表,头指针head和尾指针tail(指向链表的最后一个结点)均指向头结点。读取数据信息,申请新的结点空间,将数据存于新结点。将新结点插入到链表最后一个结点的后面,tail指针指向新插入的结点,重复的操作直到输入结束。尾结点指针域赋NULL。【例10.9】编写函数,在表尾插入结点生成单链表。struct node*createtail()struct node*head,*p,*tail;int data;head=(struct node*)malloc(sizeof(struct node);/*生成头结点*/tail=head;/*尾指针指向最后一个结点*/scanf(%d,/*读取数据*/,10.3 动态数据结构链表,while(data=0)p=(struct node*)malloc(sizeof(struct node);/*生成新结点p*/p-data=data;/*读入的数据存放到结点p的数据域*/tail-next=p;/*将新结点p插入到表尾*/tail=p;/*修改尾指针tail指向当前的尾结点*/scanf(%d,/*返回头指针*/,10.3 动态数据结构链表,10.3 动态数据结构链表,10.3 动态数据结构链表,若采用从表头插入新结点的方式,则创建链表的主要步骤为:生成只含有头结点的空链表,定义头指针head指向头结点。读取数据信息,申请新的结点空间,将数据存于新结点。将新结点插入到头结点后面。重复的操作直到输入结束。【例10.10】编写函数,在表头插入结点生成单链表。struct node*createhead()struct node*head,*p;int data;head=(struct node*)malloc(sizeof(struct node);/*生成头结点*/head-next=NULL;/*置为空表*/scanf(“%d”,/*读入的数据存放到结点p的数据域*/,10.3 动态数据结构链表,p-next=head-next;/*将新结点插入到头结点之后*/head-next=p;/*修改头结点的指针域指向新插入结点*/scanf(%d,/*返回头指针*/,10.3 动态数据结构链表,10.3 动态数据结构链表,【例10.11】编写函数,输出单链表内容。void output(struct node*head)/*输出链表*/struct node*p;printf(the linklist is:n);p=head-next;/*指针变量p获得头结点后继结点的地址*/while(p!=NULL)/*判断指针变量p是否为NULL,为NULL表示链表结束*/printf(%6d,p-data);/*输出指针变量p结点的内容*/p=p-next;/*指针变量p指向链表下一个结点*/return;,10.3 动态数据结构链表,删除结点在单链表中删除指定结点的主要步骤为:找到要删除的p结点和p结点的前驱结点q(由于单向链表有头结点,所以前驱结点一定存在)。删除该结点:修改前驱结点的指针域指向待删除结点的后继结点,并释放被删除结点所占用的空间。注意:删除结点后,一定要释放被删除结点所占空间。否则,该结点会成为游离的、不可再用的空间。,【例10.13】编写函数,在单链表中删除值为x的结点。struct node*delete(struct node*head,int x)/*从链表中删除值为x的结点*/struct node*p,*q;q=head;/*q指向头结点*/p=head-next;/*p指向第一个结点*/while(p/*返回头指针*/,10.3 动态数据结构链表,10.3 动态数据结构链表,插入结点插入到p结点之后,相应C语句为:s-next=p-next;s的指针域指向p的后继结点。p-next=s;p的指针域指向新插入结点s。,10.3 动态数据结构链表,在结点p之前插入新结点,首先要找到p的前驱结点q。相应C语句为:s-next=p;s的指针域指向p。q-next=s;q的指针域指向新插入结点s。,10.3 动态数据结构链表,【例10.14】编写函数,在单链表中值为x的结点之前插入一个值为y的结点。struct node*insert(struct node*head,int x,int y)/*在链表值为x的结点前插入值为y的结点*/struct node*p,*q,*s;s=(struct node*)malloc(sizeof(struct node);/*生成新结点s*/s-data=y;/*将y存放在新结点中*/q=head;/*q指向头结点*/p=head-next;/*p指向第一个结点*/while(p-data!=x)/*保持p指向当前结点,q指向p结点的前驱*/,10.3 动态数据结构链表,if(p=NULL)/*未找值为x的结点,返回空*/printf(not find xn);free(s);return(head);s-next=p;/*插入s结点到p之前*/q-next=s;return(head);/*返回头指针*/,10.3 动态数据结构链表,【例10.15】链表的综合操作。#inlude data.h#inlude func.c#inlude stdio.hmain()struct node*head,*p;int x,a,b;char ch;do printf(n1:createn2:searchn3:insertn4:deleten5:outputn0:exitn);printf(please select:);ch=getch();while(!(ch=0)ch=getch();/*输入不在0到5之间无效*/putchar(ch);printf(n);,10.3 动态数据结构链表,switch(ch)case 1:/*若选择1,创建链表*/printf(please enter data:);head=createhead();/*创建链表*/output(head);/*输出创建后的链表*/break;case 2:/*若选择2,在链表中查找数据*/printf(please enter data:);scanf(%d,10.3 动态数据结构链表,case 3:/*若选择,在链表中插入数据*/printf(please enter data(insert b before a)a,b:);scanf(%d%d,10.3 动态数据结构链表,while(ch!=0);,10.4枚举类型,枚举类型的定义枚举类型的定义格式如下:enum 枚举类型名枚举常量1,枚举常量2,枚举常量n;enum weekSunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;enum是用来定义枚举类型的关键字,枚举类型名应符合标识符定义的规则,enum和枚举类型名共同构成枚举类型的类型名。花括弧内是该枚举类型所有可能的取值列表,也就是枚举常量列表。每个枚举常量都是有意义的标识符;枚举常量表面上是标识符,实际存储的是整型值。在系统默认情况下,第一个枚举常量的值是0,以后每个枚举常量的值是前一个常量的值加1。枚举常量的值在定义后不能被修改。枚举常量也可显示赋值,未被显式赋值的枚举常量的值是前一个常量值加1。enum weekSunday=7,Monday=1,Tuesday,Wednesday,Thursday,Friday,Saturday;,10.4枚举类型,枚举类型变量的定义和引用枚举类型变量的定义定义枚举类型的同时定义变量。enum colorsred,blue,green,yellow c1,c220;先定义枚举类型,然后定义变量。enum colorsred,blue,green,yellow;enum colors c1,c220;如果之后不再使用此枚举类型,可定义类型时省略枚举类型名并同时定义变量。enum red,blue,green,yellow c1,c220;枚举类型变量的引用枚举类型变量的取值范围只能是其枚举类型定义时所枚举的枚举常量。枚举常量可赋值给枚举变量。整型和枚举类型之间不能相互赋值,若要赋值,需进行强制类型转换。,10.4枚举类型,【例10.16】考虑程序执行结果,体会枚举类型的用法。main()enum colorsred,blue,green,yellow c1,c2;c1=blue;c2=(enum colors)1;if(c1=c2)printf(yes);else printf(no);程序运行结果为:yes,10.4枚举类型,可以比较枚举类型变量的大小,枚举变量的比较相当于它们所隐含整数值的比较。枚举变量可以作为循环变量来控制循环。【例10.17】考虑程序执行结果,体会枚举类型的用法。enum weekSunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;main()enum week w;int k=0;for(w=Sunday;w=Saturday;w+,k+)printf(%2d,k);程序运行结果为:0 1 2 3 4 5 6,10.4枚举类型,枚举类型变量无法直接读入。枚举类型直接输出也只是显示整数,而不能显示标识符形式的枚举常量。【例10.18】仔细阅读下面例题,考虑程序执行结果,体会枚举类型的用法。enum weeksun,mon,tue,wed,thu,fri,sat;main()enum week w,m;int day;char*name=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;printf(please enter what day today(0-sun,1-mon,2-tue,3-wed,4-thu,5-fri,6-sat):);scanf(%d,10.4枚举类型,for(m=w;m!=(w+6)%7;m=(m+1)%7)printf(%s,namem);运行时输入4,程序运行结果为:please enter what day today(0-sun,1-mon,2-tue,3-wed,4-thu,5-fri,6-sat):4 Thursday Friday Saturday Sunday Monday Tuesday,10.5共用体类型,共用体类型的定义共用体类型定义的格式为:union 共用体名类型名 成员名1;类型名 成员名2;类型名 成员名n;union是关键字,标识共用体类型。共用体名应符合标识符的命名规则,union和共用体名共同构成共用体类型名。共用体的所有成员共占一段内存。某个时刻只有一个成员起作用,其它成员无效。整个共用体所占的内存大小等于占用内存单元最多的那个成员所占用的空间。花括弧中共用体成员定义和结构体成员定义方式相同。共用体类型的成员可以是构造类型,但通常情况下是基本类型的。,10.5共用体类型,共用体变量的定义和引用变量的定义定义共用体类型的同时定义变量。先定义共用体类型,然后定义共用体变量。如果之后不再使用此共用体类型,可定义类型时省略共用体名并同时定义变量。union examplechar c1;int c2;float c3;un1,un2;,10.5共用体类型,union examplechar c1;int c2;float c3;uinon example un1,un2;union char c1;int c2;float c3;un1,un2;,10.5共用体类型,变量的引用引用共用体变量时,一定要记住某一时刻只能有某一个成员起作用。只能引用共用体变量的成员,而不能引用整个共用体变量。引用形式为:共用体变量名.成员名un1.c1,un2.c2,un1.c3是合法的引用。可通过指向共用体的指针变量引用共用体变量,引用形式为:共用体指针变量-成员名 或(*共用体指针变量).成员名语句“union un*pu;pu=”之后,(*pu).c,pu-k是合法的引用。说明:给共用体变量赋值时,只能对共用体的一个成员赋值,而不能对整个共用体变量赋值。对共用体变量而言,只有最近一次被赋值的成员是有效的,其他成员无效。,10.5共用体类型,共用体变量不能在定义时初始化。若共用体的成员是构造类型的,则需要逐级引用至最低级的成员。共用体变量的地址和共用体各个成员的地址是相同的。但是它们的类型是不同的。【例10.19】学校某个协会既有学生成员又有教师成员,学生信息包括姓名、年龄、职业(学生S)和年级,教师信息包括姓名、年龄、职业(教师T)和职称。输入协会成员列表,并输出年龄小于25岁的成员信息。,10.5共用体类型,#define N 5#include stdio.hstruct associatorchar name10;/*姓名*/int age;/*年龄*/char job;/*职业*/union/*年级、职称的公用体*/int grade;char position10;category;,10.5共用体类型,main()struct associator memberN;int i;printf(please enter associators:name age job grade/position:n);for(i=0;iN;i+)/*输入数据*/scanf(%s%d%c,memberi.name,10.5共用体类型,if(memberi.job=S)printf(%dn,memberi.category.grade);else printf(%sn,memberi.category.position);输入5条信息,运行结果为:please enter associators:name age job grade/position:li 50 T professorwang 33 T professorzhang 24 T lectorzhao 21 S 3liu 26 S 1associators(age25):zhang 24 T lectorzhao 21 S 3,10.6 用户自定义类型,用typedef声明基本类型定义基本类型的新类型名的形式为:typedef 基本类型名 新类型名;例如,typedef char CHARACTER;CHARACTER ch80,c;用typedef声明构造类型数组类型的声明定义数组类型的新类型名的形式为;typedef 新类型名数组长度;例如,typedef char STRING80;STRING str1,str2;,10.6 用户自定义类型,结构体、共用体类型的声明类型关键字(struct或union)类型名 类型名 成员名1;类型名 成员名2;类型名 成员名n;typedef类型关键字(struct或union)类型名 新类型名;,10.6 用户自定义类型,【例10.20】注意类型DATA使用。struct dataint year;int month;int day;typedef struct data DATA;main()DATA d;d.year=1990;d.month=7;d.day=9;printf(year=%dmonth=%dday=%d,d.year,d.month,d.day);程序运行结果为:year=1990month=7day=9,10.6 用户自定义类型,typedef类型关键字(struct或union)类型名 类型名 成员名1;类型名 成员名2;类型名 成员名n;新类型名;typedef struct dataint year;int month;int day;DATA;,10.6 用户自定义类型,typedef类型关键字(struct或union)类型名 成员名1;类型名 成员名2;类型名 成员名n;新类型名;,10.6 用户自定义类型,【例10.21】注意类型TEST使用。typedef unionint x;float y;TEST;main()TEST d;d.x=99;printf(d=%dn,d.x);d.x=1.99;printf(d=%fn,d.y);程序运行结果为:d=99d=1.990000,10.6 用户自定义类型,枚举类型的声明enum 枚举类型名枚举常量列表;typedef enum 枚举类型名 新类型名;例如,enum colorsred,blue,green,yellow;typedef enum colors COLOR;typedef enum 枚举类型名枚举常量列表新类型名;例如,typedef enum colorsred,blue,green,yellow COLOR;typedef enum 枚举常量列表 新类型名;例如,typedef enum red,blue,green,yellow COLOR;用户自定义类型的用途减少书写工作量,增加程序可读性。提高程序的可移植性。,