资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,第,9,章,结构体与联合体,9.1,结构体类型变量,定义结构类型变量包括两个方面:首先要定义结构体类型,以便确定该类型中有哪些成员,各成员属于什么数据类型;然后再定义属于该结构体类型的变量。,9.1.1,结构体类型变量的定义,1.,定义结构体类型,定义结构体类型的一般形式如下:,struct,结构体类型名,成员表,;,其中在“成员表”中定义了该类型中有哪些成员,各成员属于什么数据类型。,2.,定义结构体类型变量,当在程序中定义了某个结构体类型以后,就可以定义属于该结构体类型的变量了。,定义结构体类型变量的一般形式为,struct,结构体类型名,变量表;,定义结构体类型与定义结构体类型变量是分开说明的。,C,语言还允许在定义结构体类型的同时定义结构体类型变量。其形式为,struct,结构体类型名,成员表,变量表;,C,语言还允许直接定义结构体类型变量。其形式为,struct,成员表,变量表;,在程序中定义了某结构体类型的变量后就可以被引用。,结构体变量的一般引用方式如下:,结构体变量名,.,成员名,其中“,.,”为结构体成员运算符,它的优先级最高。由此可以看出,在引用结构体变量时,一般是对其中的成员逐个引用。,9.1.2,结构体类型变量的引用,C,语言规定,结构体类型的定义可以嵌套,9.1.3,结构体的嵌套,与普通变量一样,在定义结构体类型变量的同时也可以对结构体类型变量赋初值。但,C,语言规定,只能对全局的或静态的局部结构体类型变量进行初始化。为了将结构体类型变量定义为静态存储类型,在定义时应加上,static,关键字。但是,目前在大部分计算机系统中,对结构体类型变量初始化时不必加,static,关键字,其原理与普通数组的初始化一样。,9.1.4,结构体类型变量的初始化,在对结构体类型变量进行初始化时,与普通数组一样,只不过在结构体变量中,各成员的数据类型可以不同,而普通数组中的各元素类型是相同的。,与基本数据类型的变量一样,结构体类型的变量也可以作为函数参数,并且,还可以定义结构体类型的函数。,9.1.5,结构体与函数,1.,结构体类型变量的成员作为函数参数,与数组元素可以作为函数参数一样,结构体类型变量中的成员也可以作为函数参数。在这种情况下,在被调用函数中的形参是一般变量,而调用函数中的实参是结构体类型变量中的一个成员,但要求它们的类型应一致。,2.,结构体类型变量作为函数参数,与一般变量可以作为函数参数一样,结构体类型的变量也可以作为函数参数。在这种情况下,在被调用函数中的形参是结构体类型的变量,调用函数中的实参也是结构体类型的变量,但要求它们属于同一个结构体类型。,3.,结构体类型的函数,与定义标准数据类型函数一样,,C,语言也允许定义结构体类型的函数。结构体类型函数的返回值是结构体类型的数据。,9.2,结构体数组,与整型数组、实型数组、字符型数组一样,在程序中也可以定义结构体类型的数组。但,C,语言规定,同一个结构体数组中的元素应为同一种结构体类型。,9.2.1,结构体数组的定义与引用,与普通数组一样,结构体类型数组也能作为函数参数,并且形参与实参结合的方式完全一样。如果在被调用函数中改变了结构体类型形参数组元素中各成员值,实际上也就改变了结构体类型实参数组元素中的各成员值。因为结构体类型形参数组与结构体类型实参数组是同一个存储空间。,9.2.2,结构体数组作为函数参数,9.3,结构体与指针,结构体类型的指针变量指向结构体类型变量或数组,(,或数组元素,),的起始地址。,9.3.1,结构体类型指针变量的定义与引用,当结构体类型的指针变量,p,指向一个结构体类型变量后,下列,3,种表示是等价的:,结构体变量名,.,成员,(*p).,成员,p,成员,它们都表示结构体变量中的一个成员。,结构体类型指针可以指向结构体类型的变量,因此,当形参是结构体类型指针变量时,实参也可以是结构体类型指针(即地址)。在结构体类型指针作为函数参数的情况下,由于传送的是地址,因此,如果在被调用函数中改变了结构体类型形参指针所指向的地址中的值,实际上也就改变了结构体类型实参指针所指向的地址中的值。,9.3.2,结构体类型指针作为函数参数,结构体类型指针也可以指向数组或数组元素,因此,当形参是结构体类型指针变量时,实参也可以是结构体类型数组名或数组元素的地址。,与标准数据类型的数组与指针一样,在结构体类型数组指针作函数参数时,也可以有以下,4,种情况:,(,1,)实参与形参都用结构体类型数组名;,(,2,)实参用结构体类型数组名,形参用结构体类型指针变量;,(,3,)实参与形参都用结构体类型指针变量;,(,4,)实参用结构体类型指针变量,形参用结构体类型数组名。,9.4,链 表,1,链表的一般结构,链表由结点元素组成。为了适应链表的存储结构,计算机存储空间被划分为一个一个小块,每一小块占若干字节,通常称这些小块为存储结点。,将存储空间中的每一个存储结点分为两部分:一部分用于存储数据元素的值,称为数据域;另一部分用于存放下一个数据元素的存储序号(即存储结点的地址),称为指针域。,9.4.1,链表的基本概念,在链表中,用一个专门的指针,HEAD,指向链表中第一个数据元素的结点(即存放第一个数据元素的存储结点的序号)。链表中最后一个元素后面已没有结点元素,因此,链表中最后一个结点的指针域为空(用,NULL,或,0,表示),表示链表终止。,2,结点结构体类型的定义,在,C,语言中,定义链表结点结构的一般形式如下:,struct,结构体名,数据成员表;,struct,结构体名 *指针变量名;,;,3,结点的动态分配,在,C,语言中,可以利用,malloc,函数向系统申请分配链表结点的存储空间,其形式为,malloc(,存储区字节数,),该函数返回存储区的首地址。,1,在链表中查找指定元素,在对链表进行插入或删除的运算中,总是首先需要找到插入或删除的位置,这就需要对链表进行扫描查找,在链表中寻找包含指定元素值的前一个结点。当找到包含指定元素的前一个结点后,就可以在该结点后插入新结点或删除该结点后的一个结点。,9.4.2,链表的基本运算,2,链表的插入,链表的插入是指在原链表中的指定元素之前插入一个新元素。,要在链表中包含元素,x,的结点之前插入一个新元素,b,。其插入过程如下:,(,1,)用,malloc(),函数申请取得新结点,p,,并置该结点的数据域为,b,。即令,p,d,b,。,(,2,)在链表中寻找包含元素,x,的前一个结点,设该结点的存储地址为,q,。链表如图,8.3,(,b,)所示。,(,3,)最后将结点,p,插入到结点,q,之后。为了实现这一步,只要改变以下两个结点的指针域内容:,使结点,p,指向包含元素,x,的结点(即结点,q,的后件结点),即令,p,next,q,next,使结点,q,的指针域内容改为指向结点,p,,即令,q,next,p,3,链表的删除,链表的删除是指在链表中删除包含指定元素的结点。,为了在链表中删除包含指定元素的结点,首先要在链表中找到这个结点,然后将要删除结点放回到可利用栈。,要在链表中删除包含元素,x,的结点。其删除过程如下:,(,1,)在链表中寻找包含元素,x,的前一个结点,设该结点地址为,q,。则包含元素,x,的结点地址,p,q,next,。,(,2,)将结点,q,后的结点,p,从链表中删除,即让结点,q,的指针指向包含元素,x,的结点,p,的指针指向的结点,即令,q,next,p,next,(,3,)将包含元素,x,的结点,p,释放。此时,链表的删除运算完成。,C,语言中中的联合数据类型可以满足这种需要。联合体又称为共用体,意为各种不同数据共用同一段存储空间。,与结构体类似,为了定义联合体类型变量,首先要定义联合体类型,说明该联合体类型中包括哪些成员,它们各属于何数据类型,然后再定义该类型的变量。,9.5,联 合 体,定义联合体数据类型的一般形式为,union,联合体名,成员表,;,下面对联合体类型变量作几点说明:,(,1,)由于一个联合体变量中的各成员共用一段存储空间,因此,在任一时刻,只能有一种类型的数据存放在该变量中,即在任一时刻,只有一个成员的数据有意义,其他成员的数据是没有意义的。,(,2,)在引用联合体变量中的成员时,必须保证数据的一致。,(,3,)在定义联合体变量时不能为其初始化,并且,联合体变量不能作为函数参数。,(,4,)联合体类型与结构体类型可以互相嵌套,即联合体类型可以作为结构体类型的成员,结构体类型也可以作为联合体类型的成员。,9.6,枚举类型与自定义类型名,(,1,)先定义枚举类型,然后定义该枚举类型的变量。,定义枚举类型的一般形式为,enum,枚举类型名,枚举元素列表,;,其中在枚举元素列表中依次列出了该类型中所有的元素(即枚举常量),如果在定义中没有显式地给出这些元素的值,这些元素依次取值为,0,,,1,,,2,,,。,(,2,)在定义枚举类型的同时定义该枚举类型的变量。,这种定义方法的一般形式为,enum,枚举类型名,枚举元素列表,变量表;,(,3,)直接定义枚举类型变量。,这种定义方法的一般形式为,enum ,枚举元素列表,变量表;,9.6.1,枚举类型,在使用枚举类型数据时,要注意以下几个问题:,(,1,)不能对枚举元素赋值,因为枚举元素本身就是常量(即枚举常量)。,(,2,)虽然在程序中不能对枚举元素赋值,但实际上,每个枚举元素都有一个确定的整型值。,(,3,),C,语言允许将一个整型值经强制类型转换后赋给枚举类型变量。,在一个,C,程序中,可以使用,C,提供的标准数据类型名(如,int,,,char,,,float,,,double,等),也可以使用用户自己定义的数据类型名(如结构体类型,联合体类型,枚举类型等)。除此之外,,C,语言还允许用,typedef,声明新的类型名来代表已有的类型名,称为自定义类型名。,自定义类型名的一般形式为,typedef,原类型名 新类型名;,它指定用新类型名代表原类型名。,9.6.2,自定义类型名,
展开阅读全文