《C语言程序设计第7章.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计第7章.ppt(93页珍藏版)》请在三一办公上搜索。
1、第7章结构与共用,返回总目录,目录,7.1结构类型,7.2共用类型,7.3枚举类型,7.5自定义类型,7.4位域,返回总目录,7.6习题七,基本要求:)熟悉结构类型的定义与使用;)熟悉共用类型的定义与使用;)掌握枚举类型、位域及自定义类型的定义与使用学习重点:)结构类型的定义与使用;)自定义类型的定义与使用;,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,返回目录,在日常生活中,我们常会遇到一些需要填写的登记表,如成绩表、通讯地址等,如图7.1所示。这些表中集合了各种标准类型数据,无法用前面学过的任一种数据类型完全描述,因此,C语言引入一种能集不同数据类型于一体的数据类型结构类型(
2、structure)。,图7.1,结构类型的定义,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,定义一个结构类型的一般形式为:struct 结构名 类型成员名1;类型成员名2;;花括弧内是该结构类型中的各个成员(或称分量),是一组系统标准变量类型,由它们组成一个结构类型。若把成员的集合称为“域表”,每一个成员则称为一个域。成员的命名规则与标准变量命名规则相同。,结构类型的定义,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,例如,通讯录的结构类型定义为:struct addr char name20;/*姓名*/char department30;/*部门*/char a
3、ddress30;/*住址*/long int zip;/*邮编*/long int phone;/*电话号码*/char email30;/*Email*/;,结构类型的定义,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,同样,成绩表的内容可以用另一个结构类型来表示:struct score char grade20;/*班级*/long int number;/*学号*/char name20;/*姓名*/char sex;/*性别*/float maths;/*数学成绩*/float database;/*数据库成绩*/float english;/*英语成绩*/;,结构类型
4、的定义,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,结构类型变量的定义(3种方式),先定义结构类型再定义变量名其一般形式为:struct 结构名 类型成员名1;类型成员名2;;struct 结构名结构变量名表;,例如:struct score char grade20;long int number;char name20;char sex;float maths;float database;float english;struct score stu1,stu2;,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,(2)在定义类型的同时定义变量这是一种双重定义,其一般
5、形式为:struct 结构名 类型成员名1;类型成员名2;结构变量名表;,例如:struct score char grade20;long int number;char name20;char sex;float maths;float database;float english;stu1,stu2;,结构类型变量的定义(3种方式),7.1结构类型,7.1.1 结构类型的定义、初始化与引用,(3)直接定义结构类型变量若仅需要结构变量,则定义时可以不出现结构名。其一般形式为:struct 类型成员名1;类型成员名2;结构变量名表;,例如:structchar grade20;long in
6、t number;char name20;char sex;float maths;float database;float english;stu1,stu2;,结构类型变量的定义(3种方式),7.1结构类型,7.1.1 结构类型的定义、初始化与引用,上3例中的结构变量stu1与stu2定义后,具有结构类型struct score定义的结构。如图7.2所示。(图中结构变量的各个成员的值是假设的),结构类型变量的定义(3种方式),7.1结构类型,7.1.1 结构类型的定义、初始化与引用,在编译时,不对结构类型分配空间,只对结构变量分配空间。Turbo C编译器将自动地分配适当的内存区域给结构变
7、量的各个成员变量。结构变量stu1的内存分配情况(设字符占1bytes,整型数占2 bytes)如表7.1所示。,结构类型变量的定义(3种方式),7.1结构类型,7.1.1 结构类型的定义、初始化与引用,结构变量引用规则,(1)成员的访问。对结构变量中各个成员的访问,用操作符“.”表示,其格式为:结构变量名.成员名操作符“.”称为成员运算符,具有最高优先级。C允许直接赋值给一个结构变量成员,而不能将一个结构变量作为一个整体进行输入和输出。例如,若系统已经进行了如图7.2所示的定义,则将30301赋给其结构变量stu1中的number成员的正确语句是:stu1.number=30301;而以下语
8、句是错误的:scanf(%s,%ld,%s,%c,%f,%f,%f,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,(2)对成员变量可以象普通变量一样进行各种运算。下列运算是正确的:stu1.number+;+stu1.number;注意:运算stu1.number+是对stu1中的number进行自加运算,而不是先对stu1进行自加运算。,结构变量引用规则,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,(3)可以引用成员的地址,也可以引用结构变量的地址。如对于如图7.2的结构类型:scanf(%ld,/*输出stu1的首地址*/结构体变量的地址主要用于作函数参数,传递结
9、构体的地址值。,结构变量引用规则,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,结构变量的初始化,可以在定义结构变量的同时,对结构变量中的各个成员进行初始化。初始化时注意数据类型一致性。,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,例7.1在定义结构类型的同时进行结构变量的定义及初始化。#include struct addrchar name20;char department30;char address30;long int zip;long int phone;char email30;a=Liu Lin,Maths,17 BeiHuang Road,1000
10、08,856432,LL;main()printf(name:%sndepartment:%snaddress:%sn,a.name,a.department,a.address);printf(zip:%ldnphone:%ldnemail:%sn,a.zip,a.phone,a.email);,结构变量的初始化,7.1结构类型,7.1.1 结构类型的定义、初始化与引用,例7.2先定义结构类型,再进行结构变量的定义及初始化。#include main()struct addrchar name20;char depart30;char address30;long int zip;long
11、int phone;char email30;struct addr a=Liu Lin,Maths,17 BeiHuang Road,10008,856432,LL;printf(name:%sndepartment:%snaddress:%sn,a.name,a.depart,a.address);printf(zip:%ldnphone:%ldnemail:%sn,a.zip,a.phone,a.email);,结构变量的初始化,7.1结构类型,7.1.2 结构类型数组,1.结构数组定义,与定义结构变量的方法相似,结构数组只需说明其为数组即可。例如,定义一个能保存35个同学的通讯录结构数
12、组,格式1为:struct addrchar name20;char depart30;char address30;long int zip;long int phone;char email30;struct addr stu35;,7.1结构类型,7.1.2 结构类型数组,与定义结构变量的方法相似,结构数组只需说明其为数组即可。例如,定义一个能保存35个同学的通讯录结构数组,格式2为:struct addrchar name20;char depart30;char address30;long int zip;long int phone;char email30;stu35;,1.结
13、构数组定义,7.1结构类型,7.1.2 结构类型数组,与定义结构变量的方法相似,结构数组只需说明其为数组即可。例如,定义一个能保存35个同学的通讯录结构数组,格式3为:struct char name20;char depart30;char address30;long int zip;long int phone;char email30;stu35;,1.结构数组定义,7.1结构类型,7.1.2 结构类型数组,2.结构数组的初始化,示例一在定义结构类型的同时进行结构数组的定义及初始化。#include struct addrchar name20;char department30;ch
14、ar address30;long int zip;long int phone;char email30;stu3=Liu Lin,Maths,17 BeiHuang Road,100008,856432,LL,Huang Lu,Office,118 HengHuanRoad,100070,833932,“Huang_L”,Wang Min,Design,1010 Zhongshan Road,400030,674322,WangM;,7.1结构类型,7.1.2 结构类型数组,示例二先定义结构类型,再进行结构数组的定义及初始化。#include struct addrchar name20;
15、char department30;char address30;long int zip;long int phone;char email30;struct addr stu3=Liu Lin,Maths,17 BeiHuang Road,100008,856432,LL,Huang Lu,Office,118 HengHuanRoad,100070,833932,“Huang_L”,Wang Min,Design,1010 Zhongshan Road,400030,674322,WangM;,2.结构数组的初始化,7.1结构类型,7.1.3 结构类型数据的指针,1.指向结构变量的指针,
16、(2)定义指向结构类型变量的指针变量:struct 结构名*指针变量名;也可将所定义的指针变量指向结构类型变量(注意,它只能指向一个结构类型变量,而不能指向结构类型变量的某一成员)。如:指针变量=(3)引用形式如下:指针变量-成员其中算符“-”称为指向运算符,由一个减号“-”和一个小于号“”组成。下面是与指向运算符相关的几种运算:,下面用简单例子来说明指向结构变量的指针变量的应用,指针指向的示意图如图7.4。在这段程序中,前两个printf函数是输出stu1的各个成员的值,后两个printf函数使用p-num的形式来输出stu1各成员的值,而结果是相同的。,7.1结构类型,7.1.3 结构类型
17、数据的指针,1.指向结构变量的指针,例7.3:,在C语言中,当用一个指针变量p指向某个结构变量后,则以下三种结构成员的引用是等价的:结构变量.成员名;p-成员名;(*p).成员名;一般采用前两种方法之一。,7.1结构类型,7.1.3 结构类型数据的指针,1.指向结构变量的指针,7.1结构类型,7.1.3 结构类型数据的指针,2.指向结构数组的指针,可以用指针或指针变量来指向结构数组及其元素,其定义和使用原则与指向结构变量的指针相同。,例7.4:,7.1结构类型,7.1.3 结构类型数据的指针,3.用指向结构的指针作函数参数,把一个结构变量的值传递到另一个函数,有3种方式:传递结构成员:把结构变
18、量的成员按普通变量一样进行按值传递,此时调用函数仅使用结构的部分成员。传递结构变量:用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个按值传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。传递结构指针:即用指针变量(或结构数组名)作函数参数进行传送,这里由实参传向形参的只是地址,从而减少了时间和空间的开销。,例7.5,例7.6:,7.1结构类型,7.1.4 结构的嵌套,结构类型的嵌套结构就是成员也可以是一个结构变量,即允许“嵌套”的结构类型。例如图7.6所示的结构类型。,由于成员本身又属一个结构类型,在访问成员时,则要用若干个成员运算符,逐级找到最低一
19、级的成员。系统只能对最低的成员进行赋值或存储以及运算。例如,对上面定义的struct score结构变量stu1,可以这样访问各成员:stu1.name不能是stu1.subject,因为subject本身是一个结构变量。同理,下面语句是正确的:sum=stu1.course.maths+stu2.course.maths;stu2.course.maths=stu1.course.maths;,7.1结构类型,7.1.4 结构的嵌套,7.1结构类型,7.1.5 用指针处理链表,利用在结构变量中所包含的指针类型成员,用它来指向其它结构类型数据,或指向与自身所在结构类型相同的结构类型数据,以这种
20、方法来定义一个链表。例如:struct stu int num;char name20;float score;struct stu*next;,1.链表概述,7.1结构类型,7.1.5 用指针处理链表,其中next是指针类型的成员名,它指向struct stu类型数据(即next所在的结构类型数据)。构成的链表结构如图7.8所示。该链表中每一个结点都属于struct stu类型,其成员next存放下一结点的地址。,1.链表概述,7.1结构类型,7.1.5 用指针处理链表,2.建立与输出链表,在定义结构类型时,系统并未实际分配存储空间。为能让链表在需要时动态地开辟和释放一个结点的存储单元,语言
21、编译系统的库函数提供以下相关库函数:void*malloc(unsigned size)在内存的动态存储区中分配一长度为size的连续空间。分配空间成功则返回值是一个空类型指针,指向该分配域的起始地址。否则返回值为NULL。void*calloc(unsigned n,unsigned size)在内存的动态区存储中分配n个长度为size的连续空间。分配空间成功则返回值是一个空类型指针,指向该分配域的起始地址。否则返回值为NULL。void free(void*ptr)释放由ptr指向的内存区。,链表的建立过程:定义链表数据结构;创建一个空表head=NULL;输入数据有效,重复以下操作:利用
22、malloc()函数向系统申请分配一个节点p1,并初始化p1的数据项和指针项。若是空表,将新节点连接到表头;若是非空表,将新节点接到表尾;注意:链表的头指针是非常重要的参数,因为对链表的输出和查找都要从链表的头开始,所以链表创建成功后,要返回一个链表头节点的地址,即头指针。,7.1结构类型,7.1.5 用指针处理链表,2.建立与输出链表,7.1结构类型,7.1.5 用指针处理链表,2.建立与输出链表,链表的输出过程:首先找到链表头head,只有是非空链表才将节点的值输出,若是空表则立即退出输出过程;若是非空链表,则通过指针的不断向后移动逐个输出链表中各个节点的值,直到链表尾。算法流程图如图7.
23、10所示,即:找到表头p=head;当链表非空p!=NULL时,重复以下操作;输出节点p数据p-num;跟踪p下一节点p=p-next;,7.1结构类型,7.1.5 用指针处理链表,2.建立与输出链表,head,输入1,输入2,输入3,输入4,输入1,则结束,1)建立链表:,2)输出链表:,输出1,输出2,输出3,输出4,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,从链表中删除一个节点有三种情况:删除链表头节点、删除链表中间的某一节点、删除链表的尾节点,如图7.11所示。由于删除的节点可能是链表的头,会对链表的头指针进行修改,所以删除节点函数的返回值定义为返回结构类型
24、的指针。,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,附图链表中第i个结点的删除过程,head,a1,ai-1,a,i,p,head,a1,p,s p-next;,p-next s-next;,free(r);,ai-1,ai+1,ai,an,an,(a)寻找第i1个结点,并由p指向它,(b)删除并释放第i个结点,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,将一个节点插入到一个已有的链表中也有三种情况,如图7.12所示。插入的节点可以在表头、表中或表尾。,7.1结构类型,7
25、.1.5 用指针处理链表,3.链表的删除与插入操作,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,a1,head,a4,a5,a6,(a)寻找插入位置,(b)申请新的结点,a2,a3,e,(c)插入过程,附图在链表第5个结点前插入一个结点的过程示意图,7.1结构类型,7.1.5 用指针处理链表,3.链表的删除与插入操作,例7.8创建包含学号、姓名节点的单链表。其节点数不限,表以学号为序,低学号的在前,高学号的在后,以输入姓名为空作结束。在此链表中,要求删除一个给定姓名的节点,并插入一个给定学号和姓名的节点。解题思路链表定义与输出函数可以参见前例。对于插入函数,利用mal
26、loc()函数向系统申请分配一个节点存放输入的姓名和学号,并让新的学号与各节点的学号比较,以确定插入的节点位于表头、表中或表尾。对于删除函数,应根据指定的学生姓名,在链表中从头到尾依此查找各节点,并与各节点的学生姓名比较,若查找成功(相同)则修改指针并释放内存空间,否则提示找不到节点后退出。,7.2共用类型,7.2.1 共用类型的定义,构造数据类型,也叫联合体用途:使几个不同类型的变量共占一段内存(相互覆盖)共用体类型定义定义形式:,union 共用体名 类型标识符 成员名;类型标识符 成员名;.;,例 union data int i;char ch;float f;,类型定义不分配内存,1
27、.共用类型的定义,返回目录,7.2共用类型,7.2.1 共用类型的定义,1.共用类型变量的定义,形式一:union data short i;char ch;float f;a,b,c;,形式二:union data short i;char ch;float f;union data a,b,c;,形式三:union short i;char ch;float f;a,b,c;,共用体变量定义分配内存,长度=最长成员所占字节数,共用体变量任何时刻只有一个成员存在,i,ch,f,7.2共用类型,7.2.1 共用类型的定义,1.共用类型变量的定义,例7.9解析:程序在VC中的运行结果证明了例中的
28、结构类型的存储空间(24)“大于”其各成员字节数之和(15);而共用类型的存储空间为其最长的成员所占的字节数(8)。例7.9在Turbo C中运行时,其结构类型大小为15,这说明VC和Turbo C对结构体分配内存的处理有差别,这种差别对编程一般不会构成影响,读者对这种差别有所了解即可。,7.2共用类型,7.2.1 共用类型的定义,1.共用类型变量的定义,例7.9解析:VC中为结构体变量分配内存时与Turbo C不同:VC中为结构体分配内存时,先分配一单位长度(该单位长度的大小等于结构体中占内存最多的数据类型的长度),然后在该单位长度中依次为结构中的变量分配空间,直至该单位空间不能再分配完一个
29、完整的变量时为止,就再为该结构体分配另一个单位长度的存储空间。(故不难分析出例7.9结构体大小为24),7.2共用类型,7.2.2 共用类型变量的引用,引用方式:,例 a.i=1;a.ch=a;a.f=1.5;printf(“%d”,a.i);(编译通过,运行结果不对),引用规则不能引用共用体变量,只能引用其成员,共用体变量中起作用的成员是最后一次存放的成员,例 union int i;char ch;float f;a;a=1;(),不能在定义共用体变量时初始化,例 union int i;char ch;float f;a=1,a,1.5;(),可以用一个共用体变量为另一个变量赋值,例 f
30、loat x;union int i;char ch;float f;a,b;a.i=1;a.ch=a;a.f=1.5;b=a;()x=a.f;(),7.3枚举类型,7.3.1 枚举类型的定义,定义枚举类型用enum开头。其格式为:enum 枚举类型名枚举值表;枚举值表中的各值称为枚举元素或枚举常量,是用户定义的标识符。例如定义一个枚举类型enum weekday可以是:enum weekday sun,mon,tue,wed,thu,fri,sat;其中sun、mon、.sat是枚举元素。,返回目录,7.3枚举类型,7.3.1 枚举类型的定义,用上页定义的枚举类型来定义枚举类型变量。如:en
31、um weekday workday,week_end;workday和week_end被定义为枚举变量,其值只能是sunsat之中的某个值。例如:workday=mon;week_end=sun;是正确的。当然,也可以直接定义枚举变量,如:enum sun,mon,tue,wed,thu,fri,satworkday,week_end;,7.3枚举类型,7.3.2 枚举类型在使用中的注意事项,(1)枚举元素是常量,不是变量,不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值:sun=5;mon=2;sun=mon;都是错误的。,7.3枚举类型,7.3.2 枚举类型在
32、使用中的注意事项,(2)枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2。如在weekday中,sun值为0,mon值为1,,sat值为6。可以从下面的程序得到证明:#include main()enum weekday sun,mon,tue,wed,thu,fri,sat a,b,c;a=sun;b=mon;c=tue;printf(%d,%d,%d,a,b,c);该段程序运行的结果为:0,1,2,7.3枚举类型,7.3.2 枚举类型在使用中的注意事项,(3)只能把枚举元素赋予枚举变量,不能把元素的数值直接赋予枚举变量。如:a=sum;b=mon;是正确的。而a=
33、0;b=1;是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如:语句a=(enum weekday)2;的意义是将顺序号为2的枚举元素赋予枚举变量a,相当于a=tue;语句,这个顺序号甚至还可以用表达式,如等价语句为:a=(enum weekday)(5-3);。还应该说明的是枚举元素不是字符常量也不是字符串常量,使用时不要加单、双引号。请仔细分析例7.11程序:,7.3枚举类型,7.3.2 枚举类型在使用中的注意事项,(4)但可以改变枚举元素的值,在定义时由程序员指定,如:enum weekday sun=7,mon=1,tue,wed,thu,fri.sat workday,w
34、eek_end;定义了sun为7,mon为1,以后顺序加1,sat为6。(5)枚举值可以用来作判断比较。如:if(wordday=mon).if(workdaysun).枚举值的比较规则是:按其在定义的顺序号比较。如果定义时没有人为指定,则第一个枚举元素的值认作0。故mon大于sun,而sat大于fri。,7.4位域,7.4.1 位运算符与位运算,C语言提供了六种基本位运算符和五种由位运算符与赋值符组成的复合赋值符:如表7.3、7.4所示。表7.3基本位运算符,表7.4复合赋值运算符,返回目录,7.4位域,7.4.1 位运算符与位运算,1按位与运算按位与运算符“&”是双目运算符。其功能是参与运
35、算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1,否则为0。参与运算的数以补码方式出现。例如:9&5的二进制算式为:00001001&00000101,其结果为00000001,即9&5=1。2按位或运算按位或运算符“|”是双目运算符。其功能是参加运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。,7.4位域,7.4.1 位运算符与位运算,3按位异或运算按位异或运算符“”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1,否则为0。参与运算数以补码出现.4求反运算求反运算符“
36、”为单目运算符,具有右结合性。其功能是对参与运算的数的各二进位按位求反。,7.4位域,7.4.1 位运算符与位运算,5左移运算左移运算符“”是双目运算符。其功能是把“”左边的运算数的各二进位全部右移若干位,“”右边的数指定移动的位数。符号位将随同移动,当为正数时,最高位补0。而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定,Turbo C和很多系统规定为补1。,7.4位域,7.4.2 位域,所谓“位域”,是把一个字节中的二进位划分为几个不同的区域,用于存放不需要占用一个完整的字节的二进位。每个域有一个域名,允许在程序中按域名进行操作。1位域的定义和位域变量的说明位域的定义与结
37、构类型定义相似,其形式为:struct 位域结构名 类型说明符 位域名1:位域长度1;类型说明符 位域名2:位域长度2;;,例如:struct bsint a:4;int b:4;int c:2;int d:6;,7.4位域,7.4.2 位域,位域变量的定义,形式一:struct bs int a:4;int b:4;int c:2;int d:6;stuct bs data;,形式二:struct bs int a:4;int b:4;int c:2;int d:6;data;,形式三:struct int a:4;int b:4;int c:2;int d:6;data;,位域变量说明与结
38、构变量说明的方式相同。也有三种方式:先定义后说明、同时定义说明或者直接说明。例如以下定义data为位域bs变量,共占两个字节。,7.4位域,7.4.2 位域,对于位域的定义尚有以下几点说明:(1)位域在本质上就是一种结构类型,只不过其成员是按二进位分配的。(2)一个位域必须存储在同一个字(2字节)中,不能跨两个字。(3)位域的长度不能大于一个字的长度(16)。(4)位域可以无位域名,它只用来作填充或调整位置,不能用于其它操作。(以上为在Turbo C中的结论,在其它编译系统中可能存在差异),7.4位域,7.4.2 位域,例如:struct bsunsigned a:4;unsigned:0;/
39、*表示b从下一字节开始存放*/unsigned b:5;/*从下一字节开始存放*/unsigned c:3;,7.4位域,7.4.2 位域,2位域的使用位域的使用和结构成员的使用相同,其一般形式为:位域变量名.位域名 位域允许用各种格式输出。,7.5自定义类型,7.5.1自定义类型(typedef),除了可以直接使用C提供的标准类型名(如int、char、float、double、long等)和前面介绍的结构类型、共用类型、指针、枚举类型外,语言允许由用户自己定义类型说明符,也就是说允许用户为数据类型取“别名”。这一功能要求用类型定义符typedef来完成。,返回目录,7.5自定义类型,7.5
40、.1自定义类型(typedef),例如,整型变量说明符int取自单词integer的前三个字母,为了增加程序的可读性,可把整型说明符用typedef定义为:typedef int INTEGER;以后就可用INTEGER来代替int作整型变量的类型说明。同样地,也可以用语句:typedef float REAL;来使REAL代替float作为实型变量的类型说明。经过用typedef说明后,语句INTEGER a,b;就等效于语句int a,b;而语句REAL x,y等效于语句float x,y;。,7.5自定义类型,7.5.1自定义类型(typedef),typedef定义的一般形式为:typ
41、edef 原类型名 新类型名;其中原类型名中含有定义部分,新类型名一般用大写表示,以便于区别。具体说来,定义一个新的类型名的方法是:(1)先按定义变量的方法写出定义体(如int i;);(2)将变量名换成新类型名(如将i换成COUNT);(3)在最前面加typedef(如typedef int COUNT);(4)然后可以用新类型定义变量(如COUNT X)。,7.5自定义类型,7.5.1自定义类型(typedef),另外,用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单,而且使意义更为明确,因而增强了可读性。例如:typedef int NUM100;/*定义N
42、UM为整型数组,该数组元素有100个*/NUM a,b,c;/*定义了三个数组元素达100的整型数组*/typedef char*STRING;/*定义STRING为字符指针类型*/STRING p,s10;/*p为字符指针变量,s为指针数组*/typedef int(*POINTER)()/*定义POINTER为指向函数的指针类型,函数返回整型值*/POINTER p1,p2;/*p1和p2为指向函数的指针变量*/,7.5自定义类型,7.5.1自定义类型(typedef),又例如语句:typedef structint month;int day;int year;DATE;定义了一个新类型
43、名DATE,它代表所定义的一个结构类型。这时就可以用DATE定义变量:DATE birthday;/*birthday是结构变量,注意不要写成struct DATE birthday;*/DATE*p;/*p为指向此结构类型数据的指针*/,7.5自定义类型,7.5.1自定义类型(typedef),类型定义符typedef的几点说明:(1)用typedef可以定义各种类型名,但不能用来定义变量。(2)用typedef只是对已经存在的类型增加一个类型名,而没有创造新的类型。(3)typedef与#define有相似之处,如:typedef int COUNT;和#define COUNT int
44、的作用都是用COUNT代表int。但事实上,它们两者是不同的。#define是在预编译时处理的,它只能作简单的字符串替换,而typedef是在编译时处理的。实际上它并不是作简单的字符串替换,例如:typedef int NUM10;并不是用NUM10去代替int,而是采用如同定义变量的方法那样来定义一个类型。当用typedef定义一些数据类型(尤其是象数组、指针、结构、共用类型等类型数据)时,可把它们单独放在一个文件中,然后在需要用到它们的文件中用#include命令把它们包含进来。,7.5自定义类型,7.5.1自定义类型(typedef),(4)使用typedef有利于程序的通用与移植。有时
45、程序会依赖于硬件特性,用typedef便于移植。例如,有些计算机系统int型数据用两个字节,数值范围为-3276832767;而另外一些机器则以4个字节存放一个整数,相当于前一种机型的long int型。若要把一个C程序从一个以4个字节存放整数的计算机系统移植到以2个字节存放整数的系统,一般需要将程序中的每个int变量都改为long int变量,即把“int a,b,c;”改为“long int a,b,c;”。现在可只加一行“typedef int INTEGER;”语句,而在程序中用INTEGER定义变量。当对程序进行移植时,只需将typedef定义体改为“typedef long INT
46、EGER;”即可。,7.6习题七,单项选择题,1下面正确的叙述的是()。A)结构一经定义,系统就给它分配了所需的内存单元B)结构体变量和共用体变量所占内存长度是各成员所占内存长度之和C)可以对结构类型和结构类型变量赋值、存取和运算D)定义共用体变量后,不能引用共用体变量,只能引用共用体变量中的成员2结构体类型变量在程序执行期间()。A)所有成员驻留在内存中B)只有一个成员驻留在内存中C)部分成员驻留在内存中D)没有成员驻留在内存中,返回目录,D,A,7.6习题七,单项选择题,3设有以下定义struct dateint cat;char c;int a4;long m;mydate;则在Turb
47、o C中执行语句:printf(%d,sizeof(struct date);的结果是()。A)25B)15C)18 D)8,B,7.6习题七,单项选择题,4在说明一个共用体变量时系统分配给它的存储空间是()A)该共用体中第一个成员所需存储空间B)该共用体中最后一个成员所需存储空间C)该共用体中占用最大存储空间的成员所需存储空间D)该共用体中所有成员所需存储空间的总和5共用体类型变量在程序执行期间的某一时刻()。A)所有成员驻留在内存中B)只有一个成员驻留在内存中C)部分成员驻留在内存中D)没有成员驻留在内存中,C,B,7.6习题七,单项选择题,6对于下面有关结构体的定义或引用,正确的是()。
48、struct studentint no;int score;student1;A)student.score=99;B)student LiMing;LiMing.score=99;C)stuct LiMing;LiMing.score=99;D)stuct student LiMing;LiMing.score=99;,D,7.6习题七,单项选择题,7以下说法错误的是()。A)结构体变量的名称为该结构体变量的存储首地址B)Turbo C中,结构体变量占用空间的大小为各成员项占用空间大小之和,而共用体占用空间大小为其成员项中占用空间最大的成员项所需存储空间大小C)结构体定义时不分配存储空间,
49、只有在结构体变量说明时,系统才分配存储空间D)结构体数组中不同元素的同名成员项具有相同的数据类型,A,7.6习题七,单项选择题,8若有以下说明和语句:struct teacherint no;char*name;xiang,*p=则以下引用方式不正确的是()。A)xiang.noB)(*p).no C)p-noD)xiang-no,D,7.6习题七,程序填空题,1以下程序段的作用是统计链表中结点的个数,其中first为指向第1个结点的指针。struct nodechar data;struct node*next;*p,*first;.int c=0;p=first;while(【1】)【2】
50、;p=【3】;,p!=NULL,c+,p-next,7.6习题七,程序填空题,2以下程序中使用一个结构体变量表示一个复数,然后进行复数加法和乘法运算。#include struct complex_numberfloat real,virtual;main()struct complex_number a,b,sum,mul;printf(输入a.real、a.virtual、b.real和b.virtual:);scanf(%f%f%f%f,a.real+b.real,a.virtual+b.virtual,a.real*b.real-a.virtual*b.virtual,a.virtua