第8章_自定义数据类型C++_第1页
第8章_自定义数据类型C++_第2页
第8章_自定义数据类型C++_第3页
第8章_自定义数据类型C++_第4页
第8章_自定义数据类型C++_第5页
已阅读5页,还剩90页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1第8章 自定义数据类型第8章 自定义数据类型2第8章 自定义数据类型数组是一种数据形式,其特点是多个相同类型元素集合起来;结构体是另一种重要的数据形式,其特点是不同类型成员组合起来。38.1 结构体类型结构体允许将不同类型的数据元素组合在一起形成一种新的数据类型,其声明形式为:structstruct 结构体类型名 成员列表;48.1 结构体类型structstruct STUDENT STUDENT /学生信息类型学生信息类型 intint nono; ; /声明一个整型数据成员表示学号声明一个整型数据成员表示学号 char char namename 21; 21; /声明一个字符串数据

2、成员表示姓名声明一个字符串数据成员表示姓名 char char sexsex; ; /声明一个字符数据成员表示性别声明一个字符数据成员表示性别 intint ageage; ; /声明一个整型数据成员年龄声明一个整型数据成员年龄 char char qqqq 11; 11; /声明一个字符串数据成员表示声明一个字符串数据成员表示QQQQ号号 double double scorescore; ; /声明一个浮点型数据成员表示成绩声明一个浮点型数据成员表示成绩;例如可以通过如下声明建立能表示学生信息的数据类型。58.1 结构体类型结构体类型声明一般放在程序文件开头,此时这个声明是全局的。在全局作

3、用域内,该声明处处可见,因此同作用域内的所有函数都可以使用它。结构体类型声明也可以放到函数内部,此时这个声明是局部的。若在函数内部有同名的结构体类型声明,则全局声明在该函数内部是无效的,有效的是局部声明的。68.1 结构体类型(1)结构体类型和普通数据类型(如int、char、double等)一样是类型名称,而不是该类型的一个实体,因此不会为结构体类型分配存储空间。(2)结构体类型声明时成员可以又是是结构体类型。structstruct DATA DATA intint yearyear, ,monthmonth, ,dayday; ; ;78.1 结构体类型(3)C语言的结构体类型只能用“s

4、truct 结构体类型名”表示,如“struct STUDENT”。C+兼容C语言的结构体类型,既可以用C语言方式,又可以直接用“结构体类型名”表示,如“STUDENT”。建议C+程序员使用后一种方式。88.2 结构体对象定义结构体对象称为结构体类型实例化(instance),实例化会根据数据类型为结构体对象分配内存单元。98.2.1 结构体对象的定义定义结构体对象有三种形式。1先声明结构体类型再定义对象结构体类型名 结构体对象名列表; /C+方式structstruct 结构体类型名 结构体对象名列表; /兼容的C语言方式STUDENT STUDENT a a, ,b b; ; /C+/C+

5、方式定义结构体对象方式定义结构体对象structstruct STUDENT STUDENT x x, ,y y; ; /C/C语言方式定义结构体对象语言方式定义结构体对象108.2.1 结构体对象的定义2声明结构体类型的同时定义对象一般形式为:structstruct 结构体类型名 成员列表 结构体对象名列表;structstruct DATE DATE /日期类型日期类型 intint yearyear, ,monthmonth, ,dayday; ; /年,月,日年,月,日 整型整型 d1 d1, ,d2d2; ; /定义结构体对象定义结构体对象118.2.1 结构体对象的定义3结构体对

6、象的内存形式实例化结构体对象后,对象会得到存储空间。128.2.1 结构体对象的定义图8.1 结构体对象的内存结构structstruct STUDENT STUDENT /学生信息类型学生信息类型 intint nono; ; /声明一个整型数据成员表示学号声明一个整型数据成员表示学号 char char namename 21; 21; /声明一个字符串数据成员表示姓名声明一个字符串数据成员表示姓名 char char sexsex; ; /声明一个字符数据成员表示性别声明一个字符数据成员表示性别 intint ageage; ; /声明一个整型数据成员年龄声明一个整型数据成员年龄 cha

7、r char qqqq 11; 11; /声明一个字符串数据成员表示声明一个字符串数据成员表示QQQQ号号 double double scorescore; ; /声明一个浮点型数据成员表示成绩声明一个浮点型数据成员表示成绩;138.2.2 结构体对象的初始化STAFF s1=1001,“Li Min”,STAFF s1=1001,“Li Min”,M M,1980,1980, ,1010, ,6,27006,2700. .0;0;STAFF s2=1002,Ma Gang,STAFF s2=1002,Ma Gang,M M,1978,1978, ,3 3, ,2222, ,31003100

8、. .0;0;structstruct STAFF STAFF /职员信息类型职员信息类型 intint nono; ; /工号,整型工号,整型 char char namename 21; 21; /姓名,字符串姓名,字符串 char char sexsex; ; /性别,字符型性别,字符型 DATA DATA birthdaybirthday; ; /出生日期,结构体类型出生日期,结构体类型 double double salarysalary; ; /薪水,浮点型薪水,浮点型;可以在结构体对象定义时进行初始化。148.2.3 结构体对象的使用1结构体对象成员引用使用结构体对象主要是引用它

9、的成员,其一般形式为:结构体对象名结构体对象名. .成员名成员名158.2.3 结构体对象的使用表8-1 对象成员引用运算符运算符运算符功能功能目目结合性结合性用法用法对象成员引用运算对象成员引用运算 双目双目自左向右自左向右object.memberSTAFF STAFF a a, ,b b; ;a a. .nono= =1000210002; ; /将将1000210002赋值给赋值给a a对象中的对象中的nono成员成员b b. .salarysalary= =a a. .salarysalary+ +500500. .0 0; ; /在表达式中可以引用对象成员在表达式中可以引用对象成员

10、a a. .nono+; +; /按优先级等价于按优先级等价于( (a.noa.no)+)+168.2.3 结构体对象的使用如果成员本身又是一个结构体对象,就要用成员引用运算符,一级一级地引用。例如:STAFF xSTAFF x; ;x x. .birthdaybirthday. .yearyear= =19901990, ,x x. .birthdaybirthday. .monthmonth= =5 5, ,x x. .birthdaybirthday. .dayday= =1212; ; /逐级引用成员逐级引用成员178.2.3 结构体对象的使用2结构体对象输入与输出不能将一个结构体对象

11、作为整体进行输入或输出,只能对结构体对象中的成员逐个进行输入或输出。例如:STAFF xSTAFF x; ;cincinx x. .nonox x. .sexsexx x. .salarysalary; ; cincinx x. .birthdaybirthday. .yearyearx x. .birthdaybirthday. .monthmonthx x. .birthdaybirthday. .dayday; ;cincinx x. .namename; ; 188.2.3 结构体对象的使用3结构体对象的运算结构体对象可以进行赋值运算,但不能对进行算术运算、关系运算等,例如:COMPL

12、EX COMPLEX m m, ,n n, ,k k; ;m m= =n n; ; /正确,结构体对象允许赋值正确,结构体对象允许赋值k k= =m m+ +n n; ; /错误错误,结构体对象不能做算术运算,结构体对象不能做算术运算m m n n; ; /错误错误,结构体对象不能做关系运算,结构体对象不能做关系运算回顾:19structstruct STAFF STAFF intint nono; ; char char namename 21; 21; char char sexsex; ; DATA DATA birthdaybirthday; ; double double salar

13、ysalary; ; ;STAFF STAFF a,ba,b; ;a.noa.no=1101;=1101;b.birthdat.yearb.birthdat.year=1988;=1988;a=b;a=b;sum=sum=a.salary+b.salarya.salary+b.salary; ;structstruct DATE DATE intint yearyear, ,monthmonth, ,dayday; ; ; ; 定义结构体类型定义结构体对象结构体对象的内存形式结构体对象成员的引用结构体对象的输入输出结构体对象的运算208.3 结构体与数组数组元素可以是结构体对象。218.3.1

14、 结构体数组数组元素可以是结构体类型,称为结构体数组,如一维结构体数组定义形式为:structstruct 结构体类型名 结构体数组名常量表达式;例如表示平面上若干个点的数据对象,可以这样定义:structstruct POINT POINT /点类型点类型 intint x x, ,y y; ; /平面上点的平面上点的x x、y y坐标坐标;POINT points100; POINT points100; /表示表示100100个点的数据对象个点的数据对象228.3.1 结构体数组一维结构体数组初始化形式为:其中初值序列必须按内存形式做到类型、次序一一对应。structstruct 结构体

15、类型名 结构体数组名常量表达式 =初值序列;238.3.1 结构体数组例如:初值写法中除最外面的一对大括号外,其他大括号可以省略。例如:structstruct RECT RECT /矩形框类型矩形框类型 intint leftleft, ,toptop, ,rightright, ,bottombottom; ;RECT rects3=1RECT rects3=1, ,1 1, ,1010, ,10,10, 5 5, ,5 5, ,2525, ,32,10032,100, ,100100, ,105105, ,200;200;RECT _rect3=1RECT _rect3=1, ,1 1,

16、 ,1010, ,1010, ,5 5, ,5 5, ,2525, ,3232, , 100100, ,100100, ,105105, ,200;200;248.3.1 结构体数组引用结构体数组成员需要将数组下标运算、对象成员引用运算结合起来操作,其一般形式为:数组对象数组对象 下标表达式下标表达式.成员名成员名r0.leftr0.left= =1010; ;/数组对象数组对象 下标表达式下标表达式 是结构体对象是结构体对象258.3.2 结构体数组成员结构体类型中可以包含数组成员,数组成员类型既可以是基本数据类型又可以是指针类型或结构体类型,例如表示平面三角形的数据对象,可以这样定义:st

17、ructstruct TRIANGLE TRIANGLE /三角形类型三角形类型 POINT p3;POINT p3;/由由3 3个平面上的点描述三角形个平面上的点描述三角形;268.3.2 结构体数组成员引用结构体数组成员需要将对象成员引用运算、数组下标运算结合起来操作,其一般形式为:结构体对象结构体对象. .数组成员数组成员 下标表达式下标表达式 structstruct TRIANGLE triTRIANGLE tri; ;tritri. .p0.xp0.x= =1010, ,tritri. .p0.yp0.y= =1010; ;/结构体对象结构体对象. .数组成员数组成员 下标表达式下

18、标表达式.成员名成员名278.3.2 结构体数组成员例8.1 输入20个学生信息,按成绩递减排序;成绩相同时,按学号递增排序。 1 # #include include 2 using namespace using namespace stdstd; ; 3 # #define define N 20N 20 4 structstruct tagSTUDENTtagSTUDENT /学生信息类型学生信息类型 5 intint nono; ; /学号学号 6 char char namename 2121 ; ; /姓名姓名 7 double double scorescore; ; /成绩成

19、绩 8 ;288.3.2 结构体数组成员例8.1 9 intint main()main() 10 11 structstruct tagSTUDENTtagSTUDENT A A N N , , t t; ; 12 intint i i , , j j= =2 2. .0 0; ; /消除浮点型消除浮点型bugbug 13 for for (i(i= =0 0; ; i i A A i i .no.noA A i i .A A i i .score.score; ; 15 for for (i(i= =0 0; ; i i N N- -1 1; ; i+) i+) /排序排

20、序 16 for for (j(j= =i i; ; j j N N; ; j+)j+) 17 if if ( (A A i i .score.score A A j j .no.no) 19 t t= =A A i i, , A A i i=A A j j , , A A j j =t=t; ; 298.3.2 结构体数组成员例8.1 20 for for (i(i= =0 0; ; i i N N; ; i+) i+) /输出学生信息输出学生信息 21 coutcoutA A i.noi.no,A A , ,A A i.scorei.score成员名。348.4.

21、1 指向结构体的指针表8-2 指针成员引用运算符运算符运算符功能功能目目结合性结合性用法用法-指针成员引指针成员引用运算用运算双目双目 自左向右自左向右pointer-memberp p-nono= =1000210002; ; /将将1000210002赋值给对象中的赋值给对象中的nono成员,指针成员引成员,指针成员引用运算结果是左值(即成员本身)用运算结果是左值(即成员本身)p p-salarysalary= =p p-salarysalary+ +500500. .0 0; ; /在表达式中引用指针指向的成在表达式中引用指针指向的成员员p p-no+; no+; /按优先级等价于按优先

22、级等价于(p-no)+(p-no)+358.4.1 指向结构体的指针(1)指针成员引用运算符(-)左边运算对象必须是指向结构体对象的指针,右边member必须是结构体对象中的成员名。其引用形式为:结构体指针结构体指针-成员名成员名368.4.1 指向结构体的指针(2)如果成员本身又是一个结构体对象指针,就要用指针成员引用运算符一级一级地引用成员。例如:DATE d=1981DATE d=1981, ,1 1, ,1;1;TEACHER TEACHER /教师信息类型教师信息类型 intint nono; ; /工号工号 char char namename 21; 21; /姓名姓名 DATE

23、 DATE * *pbirthdaypbirthday; ; /出生日期出生日期 a=1001,Li a=1001,Li Min,&dMin,&d, , * *p=&ap=&a; ;p p-nono= =1000110001; ; /通过指针通过指针p p引用引用a a的的nono成员成员p p-pbirthdaypbirthday-yearyear= =20082008; ; /通过指针通过指针p-p-pbirthdaypbirthday引用引用d d的的yearyear成员成员378.5 结构体与函数将结构体对象作为函数实参传递到函数中,采用值传递方式。例如:structstruct DA

24、TA DATA intint datadata; ; /整型成员整型成员 char char namename 10; 10; /数组成员数组成员;void void fun1(DATA x); fun1(DATA x); /函数原型函数原型void void fun2()fun2() DATA a=1,LiMin; DATA a=1,LiMin; fun1(a); fun1(a); /函数调用函数调用 388.5.2 结构体数组作为函数参数将结构体数组作为函数参数,采用地址传递方式。函数调用实参是数组名,形参必须是同类型的结构体数组。例如:采用地址传递方式,形参数组的首地址与实参数组完全相同

25、。void void fun3(DATA X); fun3(DATA X); /函数原型函数原型void void fun4()fun4() DATA A3=1,LiMin,2,MaGang,3,ZhangKun; DATA A3=1,LiMin,2,MaGang,3,ZhangKun; fun3(A); fun3(A); /函数调用函数调用 398.5.3 结构体指针或引用作为函数参数将结构体指针作为函数参数,采用地址传递方式。例如:void void fun5(DATA fun5(DATA * *p); p); /函数原型函数原型void void fun6()fun6() DATA a=

26、1,LiMin; DATA a=1,LiMin; fun3(&a); fun3(&a); /函数调用函数调用 408.5.4 函数返回结构体对象、指针或引用函数的返回类型可以是结构体类型,这时函数将返回一个结构体对象。例如:DATA fun8()DATA fun8() DATA a=1,LiMin; DATA a=1,LiMin; return return a a; ; /返回结构体对象,复制到临时对象中返回结构体对象,复制到临时对象中 void void fun9()fun9() DATA b DATA b; ; b b= =fun8(); fun8(); /函数返回结构体对象,并且赋值函

27、数返回结构体对象,并且赋值 418.10 链表链表是一种存储空间能动态进行增长或缩小的数据结构。链表广泛地运用于数据管理中。428.10.1 链表的概念首先设计一种称为结点(node)的数据类型:这个结构体类型中,data成员表示数据域,代表结点的数据信息。structstruct NODE NODE /结点数据类型结点数据类型 ElemTypeElemType data data; ; /数据域数据域 NODE NODE * *linklink; ; /指针域指针域;438.10.1 链表的概念图8.7 链表结构link成员表示指针域,存放另一个结点的地址,是链表中的组织者。通常,链表包含创

28、建、遍历、插入、删除等运算。448.10.2 单链表与双链表1单链表单链表每个结点包含一个指向直接后继结点的指针域,其形式为:next指向直接后继结点,由它构成了一条链。structstruct LNodeLNode /单链表结点类型单链表结点类型 intint data data; ; /数据域数据域 LNodeLNode * *nextnext; ; /指针域:指向直接后继结点指针域:指向直接后继结点;typedeftypedef LNodeLNode* * LinkListLinkList; ; /LNodeLNode为单链表结构体类型,为单链表结构体类型,LinkListLinkLis

29、t为单链表指针类型为单链表指针类型458.10.2 单链表与双链表图8.8 单链表结构指针L指向单链表头结点,头结点指向开始结点,开始结点又指向下一个结点,直到最后一个尾结点。尾结点的next为0,表示NULL指针,约定单链表的结点的next为0时表示尾结点。468.10.3 创建与销毁链表内存动态分配技术可以产生新结点的内存单元,例如:LinkListLinkList p p; ; /链表指针链表指针p p=new =new LNodeLNode; ;/分配分配LNodeLNode类型内存单元且将地址保存到类型内存单元且将地址保存到p p中中478.10.3 创建与销毁链表创建链表常用两种方

30、法:头插法和尾插法。(1)头插法建立链表CreateLinkF步骤:创建头结点*L,设置*L的next为0。动态分配一个结点s,输入s的数据域。将s插入到开始结点之前,头结点之后,即: s-next=p-next,p-next=s。重复步骤加入更多结点。488.10.3 创建与销毁链表采用头插法创建单链表的算法如下: 1 void void CreateLinkF(LinkListCreateLinkF(LinkList * *L L, ,intint n)n) 2 /头插法创建单链表,调用头插法创建单链表,调用inputinput输入函数输入数据输入函数输入数据 3 LinkListLink

31、List s s; ; 4 * *L L=new =new LNodeLNode;/;/创建头结点创建头结点 5 ( (* *L)-nextL)-next= =NULLNULL; ; /初始时为空表初始时为空表 6 for for (; n(; n 0 0; ; n-) n-) /创建创建n n个结点链表个结点链表 7 s s=new =new LNodeLNode; ; /创建新结点创建新结点 8 cincins-data;s-data; 9 s s-next=(next=(* *L)-nextL)-next; ; 10 ( (* *L)-nextL)-next= =s s; ; /头结点之

32、后头结点之后 11 12 498.10.3 创建与销毁链表图8.11 头插法建立的单链表L运行时若输入5个元素:1、2、3、4、5,则调用建立的单链表如图所示。LinkListLinkList L L; ;CreateLinkF(&LCreateLinkF(&L, ,5); 5); /创建单链表创建单链表L L508.10.3 创建与销毁链表(2)销毁链表DestroyList(&L)将链表所占用的所有内存释放掉,即销毁链表。销毁链表的步骤如下:若*L为0,表示已到链尾,销毁链表结束。令指针p指向结点*L的next,释放内存*L。*L置换为p,即*L指向直接后继结点,重复步骤直至销毁链表结束。

33、518.10.3 创建与销毁链表应用遍历算法销毁链表的算法如下: 1 void void DestroyList(LinkListDestroyList(LinkList * *L) L) /销毁单链表销毁单链表L L 2 3 LinkListLinkList q q, ,p p= =* *L;/pL;/p指向头结点指向头结点 4 whilewhile(p(p!=!=NULLNULL) ) /若不是链尾继续若不是链尾继续 5 q q= =p p-nextnext; ; /指向直接后继结点指向直接后继结点 6 delete delete p p; ; /释放结点存储空间释放结点存储空间 7 p

34、p= =q q; ; /直接后继结点直接后继结点 8 9 * *L L= =NULLNULL;/;/置为空表置为空表 10 528.10.4 链表的运算(1)链表遍历链表的输出、销毁、查找和逆序等运算都需要遍历链表。链表遍历算法的实现步骤为:令指针p指向L的开始结点。若p为0,表示已到链尾,遍历结束。令p指向直接后继结点,即p=p-next。重复步骤直至遍历结束。538.10.4 链表的运算链表遍历的算法如下:其中visit是函数指针。当调用ListTraverse遍历结点时,通过调用visit()对每个结点完成定制的操作。 1 void void ListTraverse(LinkListL

35、istTraverse(LinkList L L, , voidvoid( (* *visit)(ElemTypevisit)(ElemType* *) 2 /遍历遍历L L中的每个元素且调用函数中的每个元素且调用函数visitvisit访问它访问它 3 LinkListLinkList p p= =L L-nextnext; ; /p/p指向开始结点指向开始结点 4 whilewhile(p(p!=!=NULLNULL) ) /若不是链尾继续若不是链尾继续 5 visit(&(pvisit(&(p-data);data); 6 p p= =p p-nextnext; ; /p/p指向直接后继

36、结点指向直接后继结点 7 8 548.10.4 链表的运算(2)输出链表设计遍历结点时的visit函数:调用ListTraverse(L,visit)时扫描链表中的每个结点,并调用visit()输出结点的数据域。 1 void void visit(ElemTypevisit(ElemType * *epep) ) /实现链表遍历时结点访问实现链表遍历时结点访问的定制函数的定制函数 2 /在函数中对结点在函数中对结点* *epep实现定制的操作,例如输出实现定制的操作,例如输出 3 coutcout* *epep ;-nextnext= =p p-nextnext, , p p-nextnex

37、t= =s s; ; /结点插入算法结点插入算法618.10.4 链表的运算 1 intint ListInsert(LinkListListInsert(LinkList * *L L, ,intint i i, ,ElemTypeElemType e) e) 2 /在第在第i i个位置之前插入元素个位置之前插入元素e e 3 LinkListLinkList s s, ,p p= =* *L L; ; /p/p指向头结点指向头结点 4 whilewhile(p(p!=!=NULLNULL&i i 1) 1) /寻找第寻找第i-1i-1个结点个结点 5 p p= =p p-nextnext;

38、 ; /p/p指向直接后继结点指向直接后继结点 6 i-; i-; 7 8 ifif(p(p=NULLNULL|i i -datadata= =e e; ; /插入插入L L中中 11 s s-nextnext= =p p-nextnext, ,p p-nextnext= =s s; ;/结点插入结点插入 12 return return 1 1; ; /操作成功返回真(操作成功返回真(1 1) 13 628.10.4 链表的运算(4)删除结点结点删除操作是指将链表中的某个结点从链表中删除。删除位置可能在头结点、尾结点或者链表中间,删除操作后需要释放删除结点的内存空间。638.10.4 链表的

39、运算图8.14 单链表删除结点示意648.10.4 链表的运算图8.14 单链表删除结点示意658.10.4 链表的运算图8.14 单链表删除结点示意668.10.4 链表的运算实现上述步骤的C+语句如下:删除单链表中第i个位置结点的算法如下:p p-nextnext= =p p-nextnext-nextnext; ; /结点删除算法结点删除算法678.10.4 链表的运算 1 intint ListDelete(LinkListListDelete(LinkList * *L L, ,intint i i, ,ElemTypeElemType * *epep) ) 2 /删除第删除第i i

40、个结点个结点, ,并由并由* *epep返回其值返回其值 3 LinkListLinkList p p= =NULLNULL, ,q q= =* *L L; ; /q/q指向头结点指向头结点 4 whilewhile(q(q!=!=NULLNULL&i i=1) 1) /直到第直到第i i个结点个结点 5 p p= =q q; ; /p/p是是q q的前驱的前驱 6 q q= =q q-nextnext; ; /q/q指向直接后继结点指向直接后继结点 7 i-; i-; 8 9 ifif(p(p=NULLNULL|q q=NULLNULL) ) return return 0;0; 10 p

41、p-nextnext= =q q-nextnext; ; /结点删除算法结点删除算法 11 ifif(ep(ep!=!=NULLNULL) ) * *epep= =q q-datadata; ; 12 delete delete q q; ; /释放结点释放结点 13 return return 1 1; ; /操作成功返回真(操作成功返回真(1 1) 14 8.6 共用体共用体(union)是一种成员共享存储空间的结构体类型。一般形式为:共用体类型名与union一起作为类型名称,成员列表是该类型数据元素的集合。一对大括号是成员列表边界符,后面必须用分号(;)结束。unionunion 共用体

42、类型名 成员列表;8.6.1 共用体概念及类型定义共用体类型定义时必须给出各个成员的类型声明,其形式为:成员名列表允许任意数目的成员,用逗号(,)作为间隔。成员类型成员类型 成员名列表成员名列表; ;8.6.1 共用体概念及类型定义共用体中每个成员与其他成员之间共享内存。对于union A,m、n、a、b共享内存单元,其内存结构如图所示。union union A A int int m m, ,n n; ; /整型成员整型成员 char char a a, ,b b; ; /字符成员字符成员;8.6.1 共用体概念及类型定义图8.4 共用体内存结构示意8.6.1 共用体概念及类型定义unio

43、n union B B int int m m; ; /整型成员整型成员 char char a a, ,b b; ; /字符成员字符成员 short short n n; ; /短整型成员短整型成员;对于union B,m、a、b、n共享内存单元,其内存结构如图所示。8.6.1 共用体概念及类型定义图8.4 共用体内存结构示意8.6.1 共用体概念及类型定义比较共用体和结构体类型从UDATA类型内存结构,可以看出两个成员共享了同一段内存单元,考虑到整型有4个字节,字符型只有1个字节,相当于a是n的一部分。union union UDATA UDATA /共用体类型共用体类型 int int

44、n n; ; /整型成员整型成员 char char a a; ; /字符成员字符成员;8.6.1 共用体概念及类型定义图8.5 共用体与结构体内存结构比较8.6.1 共用体概念及类型定义从SDATA类型内存结构,可以看出两个成员n和a是各自独立的。struct struct SDATA SDATA /结构体类型结构体类型 int int n n; ; /整型成员整型成员 char char a a; ; /字符成员字符成员;8.6.1 共用体概念及类型定义图8.5 共用体与结构体内存结构比较8.6.1 共用体概念及类型定义结构体与共用体的内存形式是截然不同的。共用体内存长度是所有成员内存长度

45、的最大值,结构体内存长度是所有成员内存长度之和。建议用sizeof取它们的内存长度。8.6.2 共用体对象的定义与结构体对象相似,定义共用体对象也有三种形式:先声明共用体类型再定义共用体对象unionunion 共用体类型名 共用体对象名列表;同时声明共用体类型和定义共用体对象unionunion 共用体类型名 成员列表 共用体对象名列表;直接定义共用体对象unionunion 成员列表 共用体对象名列表;8.6.2 共用体对象的定义定义共用体对象时可以进行初始化,但只能按一个成员给予初值,例如:union union A x= 5678 ; A x= 5678 ; /正确,只能给出正确,只能

46、给出1 1个初值个初值union union A y=5A y=5, ,6 6, ,7 7, ,8; 8; /错误,试图给出错误,试图给出4 4个初值(结构体做个初值(结构体做法)法)8.6.3 共用体对象的使用共用体对象的使用主要是引用它的成员,方法是对象成员引用运算(),例如:第1句给成员m赋值5678,由于所有成员内存是共享的,因此每个成员都是这个值。第2句输出m和n为5678,输出a和b为46,因为a和b类型为char,仅使用共享内存中的一部分(4个字节的低字节),即5678(0 x162E)的0 x2E(46)。 1 x x. .m m= =56785678; ; /给共用体成员赋值

47、给共用体成员赋值 2 coutcoutx x. .m,xm,x. .n,xn,x. .a,xa,x. .b bx x. .m mx x. .n nx x. .a ax x. .b b; ; 4 x x. .n+; n+; /共用体成员运算共用体成员运算8.6.3 共用体对象的使用 1 x x. .m m= =56785678; ; /给共用体成员赋值给共用体成员赋值 2 coutcoutx x. .m,xm,x. .n,xn,x. .a,xa,x. .b bx x. .m mx x. .n nx x. .a ax x. .b b; ; 4 x x. .n+; n+; /共用体成员运算共用体成员

48、运算同时每个成员的起始地址是相同的,当运行第3句时输入1 2 3 4,x.m得到1,但紧接着x.n得到2时,x.m也改变为2了(因为共享),依次类推,最终x.b得到4时,所有成员都是这个值。第4句当x.n自增运算后,所有成员的值都改变了。8.6.3 共用体对象的使用由于成员是共享存储空间的,使用共用体对象成员时有如下特点:修改一个成员会使其他成员发生改变,所有成员存储的总是最后一次修改的结果;所有成员的值是相同的,区别是不同类型决定使用这个值的全部或部分;所有成员的起始地址值是相同的,因此通常只按一个成员输入、初始化;8.6.3 共用体对象的使用不能对共用体对象整体进行输入、输出、算术运算等操作,只能对它赋值操作。赋值实际上就是将一个对象的内容按内存形式完全复制到另一个对象中,例如:union union A oneA one, ,two=1234;two=1234;oneone= =12341234; ; /错误,类型不兼容错误,类型不兼容oneone= =twotwo; ; /正确,赋值时复制正确,赋值时复制twotwo的内存数据到的内存数据到oneone中中8.6.3 共用体对象的使用可以得到共用体对象的地址。显然,该地址与各成员的地址值相同。可以定义指向共用体对象的指针,其指向类型

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论