1第6章结构体、联合体、枚举类型C语言提供了一种聚合数据类型——结构(或结构体,structure),它是若干相关数据项的集合,其类型可以不同。结构体中所含成员的数量和大小必须是确定的,即结构体不能随机改变大小。组成一个结构体的诸成员的类型可以不同,即结构体是异质的。联合(或共用体,union)类型是一种“可变身份”的数据类型,可在不同的时候在同一存储单元里存放不同类型的数据。26.1结构体与结构变量6.1.1结构体类型的定义一般形式:struct结构类型名{成员表;};structstudent{charname[20];intorder,id;intage;charaddress[100];intscore[10];};3定义结构体类型时应注意以下几点:①结构体成员可以是任何基本数据类型的变量,如int、char、float和double型等,这些成员的类型可以相同,但往往是不同的。②结构体成员也可以是数组、指针类型的变量。例如:structclist{intcount;char*first;char*last;};4③结构体类型可以嵌套定义,即允许一个结构体中的一个或多个成员是其他结构体类型的变量。structid_card{charname[30];charsex;charnationality[20];structdate{intyear,month,day;}birthday;char*p_addr;structdatesigned_date;longintnumber;char*office;};5structdate{intyear,month,day;};structid_card{charname[30];charsex;charnationality[20];structdatebirthday;char*p_addr;structdatesigned_date;longintnumber;char*office;};也可以采用另一种形式把各个结构体类型单独定义。6④结构体类型定义不允许递归,即:一个结构体类型的成员中不能含有类型为本结构体的变量。例如下面的说明是非法的:structwrong{charname[5];intcount;structwronga;structwrongb;};⑤在同一结构体内各成员的名称不能相同。⑥}后的分号不能省略。76.1.2结构体变量的定义为了使用结构体变量,必须先定义结构体变量。定义结构体变量常用的方法有以下三种:①先定义结构体类型,再定义结构体变量。structcoord{floatx;floaty;};structcoordfirst,second;注意,利用此种方法定义结构变量时,关键字struct和结构名必须同时出现,缺一不可。8②在定义结构体类型的同时定义结构体变量。例如:structcoord{floatx,y;}first,second;③利用无名结构体类型定义变量。其一般形式是:struct{成员表;}变量名表;例如:struct{floatx,y;}first,second;9结构体变量的内部表示定义结构类型只是声明一种数据类型的“样板”。这种样板是抽象的,还没有实体,不占用内存空间,不能在程序中对结构类型直接进行赋值、存取等操作。结构变量是实体,占用内存空间,可进行赋值、存取等操作。结构变量存储单元的分配是按照其类型的样板配置的,通常是依据各个成员在结构中出现的先后次序来分配空间。1011结构变量可以嵌套:structrectangle{structcoordtopleft;structcoordbottomrt;}mybox;12136.2结构成员的引用6.2.1引用结构成员的一般方式引用结构成员的一般方式是:结构变量名.成员名first.x表示结构变量first的成员x;first.y表示结构变量first的成员y。14引用结构成员的方式是“由整体到局部”,即首先指明是哪个结构变量,然后通过成员关系运算符“.”找到其中指定的成员。结构变量中成员可以像相同类型的简单变量那样进行相应的运算。structcoord{floatx,y;};structcoordfirst;first.x=1.5;first.y=3.8;156.2.2嵌套结构中成员的引用如果要存取最内层结构变量的成员,就要连续的使用“·”运算符,即从外层结构变量找到内层结构变量,逐层存取,直至最内层的成员。例如有如下定义:structcoord{floatx,y;};structrectangle{structcoordtopleft;structcoordbottomrt;}mybox;16为了对表示矩形的mybox变量的两个坐标点赋值,就要采用如下所示的方式:mybox.topleft.x=1.8;mybox.topleft.y=8.3;mybox.bottomrt.x=12.4;mybox.bottomrt.y=1.29;176.3结构变量的初始化6.3.1结构变量的一般初始化方式structstudentwho={Zhanghua,991105,92,91,89,87,94,0.0};对结构变量初始化的一般形式是:结构类型结构变量名={初值表};6.3.2有聚合成员的结构变量的初始化为了使层次清晰、增加程序的可读性,往往用花括号将这些聚合类型变量对应的初值整体上括起来。例如,structstudentwho={Zhanghua,991105,{92,91,89,87,94},0.0};18注意:①允许初值赋的个数少于结构变量中成员的个数,但不允许初值符的个数多于结构变量中成员的个数。structstudentwho={Zhanghua,991105,{92,91,89,87,94}};结构变量who中成员average就隐含地被初始化为0。②结构变量初始化时,不能在结构体内初始化。③初始化数据的顺序和类型应与定义结构时结构成员的顺序和类型一致。196.4结构数组6.4.1结构数组的定义及其应用由同一结构类型的变量组成的数组就称为结构数组。structscore{intscores[5];//成绩floatav;//平均分};structstudent{charname[20];//姓名longintino;//学号structscorest;//成绩单intorder;//名次}class[40];20如果要访问某个同学的名次,可采用下述形式:class[i].order如果要访问第i位同学的平均分,则相应表达式为:class[i].st.av如果要访问第i位同学的第j门功课的成绩,则相应表达式为:class[i].st.scores[j]216.4.2结构数组在内存中的表示结构数组被定义以后,在编译时就为它分配一片连续的内存空间。各数组元素是连续存放的。226.4.3对结构数组的操作①可以把一个数组元素赋予另一个数组元素,从而实现结构变量之间的整体赋值。class[5]=class[1];②可以单独地把一个结构数组元素中的一个成员的值赋予另一数组元素中的一个同类型的成员。class[5].ino=class[1].ino;③结构数组可以初始化。常用的初始化格式有两种:23struct结构名{成员表;}数组名[大小]={初值表};struct结构名{成员表;};struct结构名数组名[大小]={初值表};初值表的形式:{{…},{…},…,{…}}246.5结构和指针6.5.1指针变量作为结构成员structstudent1{char*name;longintino;structscorest;int*order;}class[N+1];作为结构成员的指针变量遵循一般指针变量的运算规则。25#includeiostream.hvoidmain(){staticstructs{charc[4],*sp;}sa={abc,def};例:分析下面程序运行之后的输出结果。staticstructt{char*cp;structsss1;}sb={ghi,{jkl,mno}};coutsa.c[0]“”*sa.sp;coutsa.c“”sa.sp;coutsb.cp“”sb.ss1.sp;cout++sb.cp“”++sb.ss1.sp;}adabcdefghimnohino26276.5.2指向结构的指针当把一个结构变量的起始地址赋予一个指针变量时,就称该指针变量指向这个结构变量。structstudent1x1;structstudent1*p;p=&x1;2829当把一个指针变量指向某个具体的结构变量后,就可以利用该指针变量来存取该结构的成员。常用的方式有两种:①利用间接成员运算符“-”来存取结构成员,其一般引用形式是:指针变量名->结构成员名注意,运算符“->”是由连字符和大于号二者组成的字符序列,它们要连在一起使用。30②利用间接访问运算符“*”来存取所指向结构变量的成员,其一般引用形式是:(*指针变量名).成员名例如,structstudent1x1,*p;p=&x1;(*p).name=Zhangsan”注意,在这种引用形式中,“(*指针变量名)”中的一对圆括号是必须有的。31综上所述,存取结构成员的方式有三种等价形式:①直接利用结构变量名,其一般形式是:结构变量名.成员名②利用指向结构变量的指针变量和间接成员运算符,其一般形式是:指针变量名->成员名③利用指向结构变量的指针变量和间接访问运算符,其一般形式是:(*指针变量名).成员名328.5.3指向结构数组的指针structperson{charname[20];charsex;intage;};structpersongroup[20];structperson*p;p=&group[0];//p=group;coutp->namep->sexp->age;33例:试分析下面程序的运行结果。#include<iostream.h>structtemp{char*s;inti;structtemp*tp;};voidmain(){staticstructtempa[]={{abcd,1,a+1},{efgh,2,a+2},{ijkl,3,a}};structtemp*p=a;inti;couta[0].sp->sa[2].tp->s;34for(i=0;i<2;i++){cout--a[i].i;cout++a[i].s[3];}cout++(p->s);couta[(++p)->i].s;couta[--(p->tp->i)].s;}35程序运行结果如下:abcdabcdabcd0e1ibceefgiijkl36