版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2020/7/10,华中科技大学计算机学院,1,C语言程序设计,The C Programming Language,华中科技大学计算机学院曹计昌,2020/7/10,华中科技大学计算机学院,2,第10章 结构与联合,结构与联合都属于C的构造类型。 对结构与联合而言,都需要先定义结构类型和联合类型,然后再根据已经定义的结构类型来定义对应的结构变量以及用已经定义的联合类型来定义对应的联合变量。 本章介绍: 结构类型和结构变量的声明,结构类型的使用; 结构类型的指针; 有结构类型参数的函数; 结构数组; 字段结构; 以及联合类型和联合变量的定义,联合变量的使用; 动态存储分配,动态数组设计; 以及
2、与动态存储分配相关的链表、栈、树等动态数据结构。,2020/7/10,华中科技大学计算机学院,3,10.1 结构概述,结构产生的背景: 程序设计语言的发展总是与数据类型的发展、丰富、以及完善联系在一起的。 变量可以认为是内存单元的有名表示。变量在处理大量同类型数据时就暴露出名字多,不利于用循环处理等一系列不足。 数组则是处理大量同类型数据的有力工具。通过数组名和下标,可以方便的描述大量同类型数据,并且可以充分利用循环来进行快速处理。 问题: 如何将类型不同而关系又非常密切的数据项组织在一起,统一加以处理? 结构产生的背景!,2020/7/10,华中科技大学计算机学院,4,描述全班学习情况的实际
3、问题,问题: 描述全班、全年级每位同学的英语、高等数学、普通物理、C语言程序设计等课程的学习情况,需要学号、班级、姓名、以及各科成绩等属性来描述。 特点:学号、班级、姓名往往用字符数组描述、性别往往用字符型描述,各科成绩则往往用整型或浮点型描述。 困难:对这些大量不同类型数据项,用数组已经不能有效解决问题。 新的需求:如何将不同的数据类型的成员(即数据项)组织起来,形成新的构造类型就是结构产生的实际背景。,2020/7/10,华中科技大学计算机学院,5,设计和使用结构类型的方法,结构类型是一种能够将不同数据类型的成员组织起来所形成的一种新的构造类型。 结构类型的设计: 在程序设计中,要先确定需
4、要被组织的数据类型,由这些数据类型说明的标识符称为结构类型的成员;通过定义结构类型将这些成员组织起来,形成新的数据类型。 结构类型的使用: 通过结构类型来声明对应的结构变量、结构指针、或结构数组。对结构变量、结构指针、或结构数组中成员的操作将最终完成所需要解决的计算任务。,2020/7/10,华中科技大学计算机学院,6,注解,有些教材中将结构类型称为结构体、聚合类型。 C中的结构在其它程序设计语言中往往称为记录(record)。 以记录为基础,可以进一步构造文件、基于记录的数据库、以及许多动态数据结构。,2020/7/10,华中科技大学计算机学院,7,10.2 结构类型声明和结构变量的声明及初
5、始化,在声明结构类型时,需要规定该结构类型包括那些成员,要说明成员的数据类型和名字。 声明结构类型是创建用户自定义数据类型的过程,它并不创建对象,即不进行存储分配。 声明结构类型的一般形式是: struct 结构类型名 成员声明表 ; 其中:struct是关键字,用以说明结构类型。结构类型名是该结构类型的名字,它应该是C的合法标识符。一对花括号界定的是成员声明表 。,2020/7/10,华中科技大学计算机学院,8,成员声明表的一般形式,数据类型1 成员名11,成员名1k; 数据类型n 成员名n1,成员名nm; 数据类型1 和数据类型n可以相同,也可以不同。 每个声明允许用逗号为分隔符说明多个同
6、类型的成员。 结构类型的声明应该以分号结束。,2020/7/10,华中科技大学计算机学院,9,例:学生学习情况的结构类型声明,struct stu_study /* stu_study是结构类型名 */ char num12; /* 学号成员,字符数组类型 */ char name9; /* 姓名成员,字符数组类型 */ char sex;/* 性别成员,字符类型 */ int English;/* 英语成员,整型 */ int Math,Physics,C; / *数学、物理、C成员,整型 */ ; 该声明定义了一个struct stu_study的结构类型.stu_study是结构类型名,
7、用以区分其他类型的结构。 struct stu_study实际上是一种新的构造类型名,可用于说明struct stu_study类型的结构变量。其在语法方面的作用与int,char等一样,起类型说明符的作用。 num、name、sex、English、Math、Physics、C是成员,它们被组织到一个新的struct stu_study的结构类型之中。,2020/7/10,华中科技大学计算机学院,10,C关于结构类型声明的规定,(1) 同一结构内的成员不能同名。但成员可以与结构外部的变量同名,也可以与其他结构的成员同名。 (2) 成员的数据类型可以是除本结构类型以外的其他任何类型。 (3)
8、结构类型可以嵌套定义,形成嵌套结构。 (4) 结构类型是包含一系列成员的构造类型,成员在内存中连续存放,成员存储分配按照结构声明体中不同声明从上向下,同一声明中从左向右的顺序进行,每个成员所占存储空间的大小由其类型确定。 (5) 一般而言,成员所占存储的大小必须在结构类型声明时确定。即C不支持动态结构类型。 注: 根据ISO/IEC 9899标准,作为一个特例,结构类型中最后一个成员可以具有不完全的数组类型,使得C可以在有限程度上支持动态结构类型。,2020/7/10,华中科技大学计算机学院,11,含柔性数组成员(flexible array member)的声明,struct dy_stu_
9、study /* dy_stu_study是结构名 */ char num12; /* 学号成员,字符数组类型 */ char name9; /* 姓名成员,字符数组类型 */ char sex; /* 性别成员,字符类型 */ int score;/* 各科成绩的柔性数组成员,动态整型数组 */ ; 可以通过动态存储分配为score数组指定大小。如果score数组依次存放英语、数学、物理、C语言4门课程的成绩,在16位机中可以为其分配42=8个字节的存储;在32位机中则需要为其分配44=16个字节的存储。称这种结构类型为有限动态结构类型。,2020/7/10,华中科技大学计算机学院,12,例
10、10.1声明一个同学通讯录的结构类型,struct address_book char name9; /* 姓名,字符数组类型 */ int age; /* 年龄,整型 */ char department50; /* 工作部门,字符数组类型 */ char address80; /* 家庭住址,字符数组类型 */ char phone_number16;/* 电话,字符数组类型 */ char mobile12;/* 手机号码,字符数组类型 */ char email50;/* 电子邮箱,字符数组类型 */ ;,2020/7/10,华中科技大学计算机学院,13,例10.2 声明一个只含有整数
11、类型和指向自身实例指针的结构类型。,struct int_node intnumber; struct int_node *next; ; 在该结构类型中: number被称为数据域, 而next被称为指向自身结构实例的指针域。,2020/7/10,华中科技大学计算机学院,14,10.2.2 结构变量的声明,结构类型的变量往往简称为结构变量,有时甚至简称为结构。 结构变量的声明有两种方式: 一是结构类型和结构变量分别声明。即:先声明结构类型,再声明结构变量。 二是结构类型和结构变量同时声明。即:在声明结构类型的同时声明结构变量。,2020/7/10,华中科技大学计算机学院,15,1结构类型和结
12、构变量分别声明,声明结构变量的一般形式是: 存储类型 struct 结构类型名 结构变量列表; 其中,存储类型可以是extern、static、auto、register,分别表示外部结构变量、静态结构变量、自动结构变量(或局部结构变量)、以及寄存器结构变量。 结构变量列表由标识符序列组成,两个标识符之间必须用逗号分隔,每个标识符对应一个结构变量。结构变量的声明应该以分号结束 。,2020/7/10,华中科技大学计算机学院,16,结构变量声明语句,struct stu_study Zhang; 就声明了一个struct dy_stu_study类型的结构变量Zhang。 而结构变量声明语句:
13、struct address_book John,Mary,Jones; 则声明了三个struct address_book类型的结构变量John,Mary和Jones。,2020/7/10,华中科技大学计算机学院,17,例10.3 用存储类型修饰结构变量声明的例子。,(1) auto struct int_node a,b,c; (2) register struct address_book addr; (3) static struct int_node x,y; (4) extern struct stu_study Wang;,2020/7/10,华中科技大学计算机学院,18,2结构
14、类型和结构变量同时声明,其一般形式为: 存储类型 struct 结构类型名 成员声明表 结构变量列表; 其中,结构变量列表由标识符序列组成,两个标识符之间要用逗号分隔,每个标识符对应一个结构变量。 并且可以通过存储类型修饰结构变量列表中的结构变量。,2020/7/10,华中科技大学计算机学院,19,结构类型和结构变量同时声明的例子,static struct point intx; inty; p1,p2; 它在声明结构类型struct point的同时,声明了struct point类型的静态结构变量p1和p2。 P1, p2具有静态生存期. struct point结构类型可以用来表示平面
15、上的一个点,成员x、y分别表示平面上点的横坐标和纵坐标。结构变量p1和p2则分别表示平面上的两个点。,2020/7/10,华中科技大学计算机学院,20,无名结构类型,一般称省略结构类型名的结构类型为无名结构类型。如: struct intx; floaty; u,v; 它声明了结构变量u和v,结构变量u、v分别都有一个整型成员x,一个浮点型成员y。 由于省略了结构类型名,在后续程序中不能再声明类似类型的变量。,2020/7/10,华中科技大学计算机学院,21,3. 用typedef定义结构类型名,用typedef可以为一个已知的结构类型进行命名。这种方法在程序设计中使用得非常普遍。例如: ty
16、pedef struct point int x; int y; point; 它将struct point结构类型命名为point,,2020/7/10,华中科技大学计算机学院,22,用point来表示struct point结构类型的声明,point u,v; 它与struct point u,v; 等价。 用typedef还可以为一个无名结构类型进行命名。如: typedef struct int x; int y; point; 则point就代表有两个整型成员x,y的结构类型。也可以用: point u,v; 说明结构变量u和v。,2020/7/10,华中科技大学计算机学院,23,1
17、0.2.3 结构变量的初始化,在声明结构变量的同时可以对其进行初始化。初始化所用的初值由初值表提供,初值表的形式与数组初始化时使用的初值表类似,是由一对花括号界定的初值序列。结构变量的初始化的一般形式是: 存储类型 struct 结构类型名 成员声明表 结构变量1=初值表1, ,结构变量n=初值表n; 或: 存储类型 struct 结构类型名 结构变量1=初值表1, ,结构变量n=初值表n;,2020/7/10,华中科技大学计算机学院,24,结构变量的初始化举例,struct stu_study char num5; char name9; char sex; int English; int
18、 Math,Physics,C; Wang=1234,Wang Wu, m,81,92,76,85 ; 它将结构变量Wang的成员num、name、sex、English、Math、Physics、C依次初始化为1234、Wang Wu、m、81、92、76、85。,2020/7/10,华中科技大学计算机学院,25,通过存储类型修饰符对结构变量的存储类型进行修饰例的例子,static struct point int x; int y; p1=1,2,p2=10,20; 它在声明struct point类型的静态结构变量p1,p2的同时,分别将其成员x、y初始化为1,2和10,20。此时,成员
19、x、y具有静态变量的特性。,2020/7/10,华中科技大学计算机学院,26,10.3 结构类型的使用,结构类型的使用包括对结构变量的引用和对结构变量中成员的引用两个方面。 对结构变量的引用包括结构变量的赋值操作、取地址操作和间访操作,以及结构变量作为函数的参数及返回值。 对结构变量中成员的引用则需要通过成员选择运算符“.”来实现。,2020/7/10,华中科技大学计算机学院,27,10.3.1 结构变量的引用 1结构变量的赋值操作,当两个结构变量的类型相同时,它们之间可以直接相互值。例如: struct planet charcode8; charname10; short visible;
20、 doublediameter; star1=12345,Venus,1,9456.35; struct planet star2; 则star2=star1;是完全合法的赋值。 赋值操作的语义是将赋值号右端结构变量中各个成员的值一一照赋给赋值号左端结构变量的各个成员。 此时结构变量star2的成员code、name、visible、diameter的值依次为12345,Venus,1,9456.35,与star1的成员的值相同。,2020/7/10,华中科技大学计算机学院,28,2结构变量的取地址操作和间访操作,可以通过单目等价。,2020/7/10,华中科技大学计算机学院,29,10.3.
21、2 通过成员选择运算符“.”访问成员,C提供了成员选择运算符“.”构成的成员选择表达式来支持对成员的访问和操作。成员选择表达式的一般形式是: 结构变量名. 成员名 其中,“.”是小数点或句号字符,称为成员选择运算符。 它是一个双目操作符,其左操作数是结构变量,右操作数是结构变量的成员。 “.”操作符具有最高优先级,由它构成的成员选择表达式在任何地方都是一个整体,表示对结构变量中成员的访问。,2020/7/10,华中科技大学计算机学院,30,设有声明语句:struct stu_study Li;下面的代码片段对struct stu_study类型的结构变量Li的各个成员进行格式化输入或赋值操作。
22、,struct stu_study Li; . scanf(%s,Li.num); strcpy(L,Li Si); Li.sex=m; Li.English=Li.Math=80; scanf(%d,2020/7/10,华中科技大学计算机学院,31,值得注意的是:,由于Li.num和L都是字符数组名,其数据类型都是char *,因此必须用scanf函数、字符串拷贝函数strcpy或gets函数进行赋值操作。 Li.num=678;或L=Li Si;都是错误的赋值方法。 但Li.num0=6; Li.num1=7 ; Li.num2=8; Li.num3=
23、0; 是合法的赋值操作。,2020/7/10,华中科技大学计算机学院,32,下面的语句输出结构变量Li的各个成员之值:,printf(%st,Li.num); printf(%st,L); putchar(Li.sex); putchar(t); printf(%dt%dt%dt%dn,Li.English,Li.Math,Li.Physics,Li.C); 其中,putchar(t);是用于格式控制。,2020/7/10,华中科技大学计算机学院,33,10.3.3 嵌套结构的声明,C标准规定:结构变量的成员的数据类型还可以是除自身之外的其他结构类型。具有结构类型成员的结构类型称为
24、嵌套结构类型,具有结构类型成员的结构变量称为嵌套结构变量。 嵌套结构的声明要遵循先声明嵌套结构类型,再声明嵌套结构类型变量的原则。这种原则称为先声明后引用原则。在声明嵌套结构类型时,应该先声明结构类型成员的结构类型,再声明嵌套结构类型。,2020/7/10,华中科技大学计算机学院,34,例10-4 大学生基本信息嵌套结构类型的声明举例。,描述大学生基本信息需要学号、姓名、性别、出生日期、家庭住址、家庭收入、联系电话等属性。 可以先定义一个日期类型,再在大学生基本信息结构类型中引入日期类型的结构成员,用以描述出生日期. 然后再声明大学生基本信息结构类型的结构变量。,2020/7/10,华中科技大
25、学计算机学院,35,先声明日期类型,struct date char month10; int day; int year; ;,2020/7/10,华中科技大学计算机学院,36,再声明大学生基本信息嵌套结构类型struct stu_info,struct stu_info char num12; /* 学号 */ char name9; /* 姓名 */ char sex; /* 性别 */ struct date birthday; /* 出生日期 */ char address60; /* 家庭住址 */ double income; /* 家庭收入 */ char phone_numb
26、er16; /* 联系电话 */ char email40; /* 电子邮箱 */ ; 其中,birthday是struct date类型的结构成员。此时,struct stu_info是一个嵌套的结构类型。 struct stu_info s; 声明了一个嵌套结构类型struct stu_info的结构变量s。,2020/7/10,华中科技大学计算机学院,37,例10.5 在嵌套结构类型声明的内部声明结构类型并声明结构类型成员,并且在声明嵌套结构类型时定义结构变量。,struct stu_info1 charnum12; charname9; charsex; struct date1 ch
27、armonth10; int day; int year; birthday; charaddress60; doubleincome; charphone_number16; charemail40; s1,s2; 此时,struct date1结构类型在struct stu_info1嵌套结构类型内部声明,同时还声明了结构成员birthday。 并且在声明嵌套结构类型struct stu_info1的同时,声明了嵌套结构类型struct stu_info1的变量s1和s2。,2020/7/10,华中科技大学计算机学院,38,10.3.4 嵌套结构中结构成员的成员的访问,嵌套结构中由于包含结
28、构成员,因此存在结构成员的成员。对嵌套结构中结构成员的成员的访问采用“.”操作符,构成结构成员的成员选择表达式。 “.”操作符的使用个数与嵌套结构的层数相等。在两层嵌套结构中,结构成员的成员选择表达式的一般形式是: 结构变量名.结构成员名.成员名 “.”操作符的结合性是从左至右,编译器对“结构变量名.结构成员名.成员名”理解为: (结构变量名.结构成员名).成员名。,2020/7/10,华中科技大学计算机学院,39,设有声明语句: struct stu_info zhang;则下面是struct stu_info类型结构变量zhang的结构成员birthday的成员选择表达式:,zhang.b
29、irthday.month 或 (zhang.birthday).month 月份成员,类型char *。 zhang.birthday.day 或(zhang.birthday).day 日成员,类型int。 zhang.birthday.year或 (zhang.birthday).year 年份成员,类型int。 成员选择表达式是左值表达式,使用时要根据其数据类型进行相关操作。 例如, zhang.birthday.day=12为正确的赋值操作。而zhang.birthday.month=July为非法赋值操作。,2020/7/10,华中科技大学计算机学院,40,例10.6 根据平面上点
30、的结构类型构造平面上线段的嵌套结构类型,说明对嵌套结构变量中结构成员的成员的引用,并求线段的长度。,#include stdio.h #include math.h struct point /* 平面上点的结构类型 */ intx,y;/* x,y是点的坐标 */ ; struct line/* 平面上线段的嵌套结构类型 */ char name6;/* 线段名称 */ struct point start;/* 线段的起点 */ struct point end;/* 线段的终点 */ ;,2020/7/10,华中科技大学计算机学院,41,void main(void) struct li
31、ne a=abc,1,1,10,10; /* 声明嵌套结构变量时对其初始化 */ double dx2,dy2,length; printf(line name is %sn,); /* 输出线段名称 */ /* 下面输出起点坐标和终点坐标 */ printf(starting point:(%d,%d)n,a.start.x, a.start.y); printf(end point:(%d,%d)n,a.end.x, a.end.y); /* 下面对线段名称和起点坐标进行格式化输入赋值 */ scanf(%s,); scanf(%d%d, ,2020/7/10,华中
32、科技大学计算机学院,42,类似的,由平面上的一个点和不包含该点的直线可以构造一个平面,可以设计出由struct point结构类型和struct line结构类型构造出的含有三层嵌套的struct plain结构类型:,struct point intx,y; ; struct line struct point start,end; ; struct plain struct point a; struct line l; ;,2020/7/10,华中科技大学计算机学院,43,声明三层嵌套的struct plain类型结构变量的声明语句如下: struct plain p=1,1,5,5,2
33、0,15; 该语句定义了struct plain类型的结构变量p,并对其进行了初始化。 下面语句表达了如何对嵌套结构变量中具有基本类型成员的进行操作: p.a.x=2; p.l.start.x=5; printf(p.l.start.x=%dn,p.l.start.x); scanf(%d, 可见,嵌套多少层,对基本类型成员的访问就需要多少个对应的“.”操作。同时,对基本类型成员进行操作时一定要符合其数据类型的要求。,2020/7/10,华中科技大学计算机学院,44,10.4 结构类型的指针,以结构类型为基类型可以派生出结构类型的指针。 结构类型的指针可以用于指向结构类型的变量。从而允许通过结
34、构类型的指针访问结构变量的成员。 结构类型的指针往往简称为结构指针。,2020/7/10,华中科技大学计算机学院,45,10.4.1 结构指针的声明和赋值,与结构变量的声明类似,结构指针的声明也有两种方式。 一是先声明结构类型,再声明结构指针。 另一种是在声明结构类型的同时声明结构指针。 例如,假设有如下关于IC卡的结构类型声明: struct IC_Card /* 声明IC卡的结构类型 */ char name9; /* 持卡人姓名 */ char account9; /* 持卡人账号 */ char password7; /* 密码 */ int balance; /* 账户余额 */ ;
35、,2020/7/10,华中科技大学计算机学院,46,下面的声明语句声明了一个struct IC_Card类型的结构指针: struct IC_Card *p; 也可以在声明IC卡的结构类型的同时声明结构指针。如: struct IC_Card char name9; char account9; char password7; int balance; *p;,2020/7/10,华中科技大学计算机学院,47,可以在声明结构指针是对其初始化,也可以先声明结构指针,然后通过对结构指针进行赋值操作使结构指针指向结构变量。 下面的代码片段对结构指针进行初始化: struct IC_Card char
36、 name20; char account9; char password7; int balance; a,*p= 它在声明结构类型的同时,声明了结构变量a和结构指针p,并通过 struct IC_Card *pa= 与a=b等价,,2020/7/10,华中科技大学计算机学院,51,下面的语句对指针pa所指结构变量a的各个成员输入赋值:,scanf(%s,(*pa).name); scanf(%s,(*pa).account); scanf(%s,(*pa).password); scanf(%d, (*pa).name、(*pa).account和(*pa).password的数据类型都是
37、char *,分别表示指向姓名、账号和密码的字符指针。 printf(*pa).account=%sn,(*pa).account); printf(*pa).password=%st,(*pa).password); printf(*pa).balance=%dn,(*pa).balance); 同理,gets(*pa).name);和strcpy(*pa).account, 54321);都是对结构变量a的字符数组成员的正确输入。,2020/7/10,华中科技大学计算机学院,53,(*pa).balance=12345;是对结构变量a的balance成员的正确赋值。 (*pa).name0
38、=c;和*(*pa).name=c; 是对a的name0的正确赋值。 *(*pa).account+2)= 6; 是对a的account2的正确赋值。 +*(*pa).account+3);和(*(*pa).account+3)+;都是对a的account3的正确自增操作。 而*(*pa).account+3)+; 属非法赋值操作。因为+虽然是后缀+,但它作用到表达式(*pa).account+3)上,而(*pa).account+3)不是左值表达式,因此操作非法。 同理,(*pa).password=12011;也属于非法赋值操作。,2020/7/10,华中科技大学计算机学院,54,10.4
39、.3 通过成员选择运算符“-”访问结构变量的成员,C提供了另外一种结构成员选择运算符“-”实现对结构变量的成员简洁高效的引用。“-”由一个减号和紧跟的大于号组成,C将其作为单个运算符处理。用“-” 访问结构变量的成员的成员选择表达式的一般形式是: 结构指针名-结构成员名 它表示引用结构指针所指结构变量的成员。“-”是双目运算符,它与“.”、“()”、“”一样具有最高优先级,结合性为左结合。 “-”的左操作数应该是结构类型的指针,而右操作数为结构指针所指结构变量的成员。 此处的结构成员名为结构变量的成员名。为了简化起见,在不产生二义的情况下,简称结构变量的成员为结构成员。 结构指针名-结构成员名
40、是一个表达式,其值为结构成员的值,其类型为结构成员值的数据类型。,2020/7/10,华中科技大学计算机学院,55,设有多种类型成员的嵌套结构类型声明如下: structdate intyear; charmonth12; shortday; ; struct mul_type charc; intn; floatd; chars12; char *ps; structdate a; structdate *pa; m=a,100,3.14f,myabcdefg,m.s,2007,July, 29, ,2020/7/10,华中科技大学计算机学院,56,下面的语句输出结构变量m的非结构类型成员之
41、值:,printf(“%ct”,pm-c);与 printf(%cn,m.c);等价,pm-c类型为char。 printf(“%dt”,pm-n); 与 printf(%dn,m.n); 等价,pm-n类型为int。 printf(“%ft”,pm-d); 与 printf(%fn,m.d); 等价,pm-d类型为float。 printf(“%st”,pm-s);与 printf(%sn,m.s); 等价,pm-s类型为char *。 printf(“%st”,pm-ps);与 printf(%sn,m.ps); 等价,pm-ps类型为char *。,2020/7/10,华中科技大学计算机
42、学院,57,下面8个表达式都表示对指针pm所指变量的结构成员m的年份成员year的引用:,pm-pa-year m.a.year (*pm).pa-yearm.pa-year pm-a.year(*pm-pa).year (*m.pa).year(*(*pm).pa).year; 它们的数据类型都是int型,值则由成员year的值决定。,2020/7/10,华中科技大学计算机学院,58,类似的,对指针pm所指变量的结构成员m的月份成员month的8种引用为:,pm-pa-monthm.a.month (*pm).pa-monthm.pa-month pm-a.month(*m.pa).mont
43、h (*pm-pa).month (*(*pm).pa).month 它们的类型都是char *,,2020/7/10,华中科技大学计算机学院,59,通过下标运算符“”或间访运算符“*”还可以对s字符数组中的元素进行操作。,如: pm-pa-month2= n; 和 m.a.month3=e; 而 *pm-ps+;和(*pm-ps)+;含义完全不同。 根据优先级和结合性,表达式*pm-ps+先做pm-ps,再对pm-ps做*操作,结果是访问m.s0,表达式的值是a,类型是char;然后再做后缀+操作,使ps指向m.s1,+作用在ps上。 而表达式(*pm-ps)+ 先做pm-ps,再对pm-p
44、s做*操作,最后进行+操作。结果是访问m.s0,该表达式将m.s0的值由m更新为n,类型是char。+作用在m.s0上。,2020/7/10,华中科技大学计算机学院,60,结论: 当“-”、“.”、“*”、前缀或后缀+和出现在同一个表达式中的时候,对表达式求值的理解极容易混淆出错。唯一的法宝是严格按照运算符的优先级和结合性,以及前缀+、前缀-、后缀+、后缀的操作语义所确定的顺序,逐步的进行分析和解释,才能正确判断表达式是合法还是非法,才能正确计算出对合法表达式的求值结果。 设有: struct T int n; char *pm; s=10,abcdef,*p= 则表10.1给出了有关表达式的
45、正确理解及等价表达式。,2020/7/10,华中科技大学计算机学院,61,表10.1 有关表达式的正确理解及等价表达式 (讲解p335),2020/7/10,华中科技大学计算机学院,62,10.5 结构类型作为函数的参数和返回值,结构类型的变量或结构类型的指针都可以作为函数的参数或者函数的返回值。 结构变量的成员,指向结构变量的成员的指针也可以作为函数的参数或函数的返回值。 对于一个物理量而言,不仅有大小,还有量纲,其声明如下: struct motion double size; /* 物理量的大小 */ char dimension12; /* 物理量的量纲 */ ;,2020/7/10,
46、华中科技大学计算机学院,63,10.5.1 结构成员或结构变量作为函数的参数,1) 结构成员作为函数的参数 结构成员作为函数的参数时,形参的声明与其他基本类型的变量一样。 例如对2个物理量,假设量纲已经相同,因此可以进行物理量大小的相加操作。对应函数原型声明如下: double add_motion_size(double,double); add_motion_size函数的实现见例10.7 p340 设有声明: struct motion b=12.5,m/s,c=26.7,m/s,d; 则调用该函数的代码为: d.size=add_motion_size(b.size,c.size);,
47、2020/7/10,华中科技大学计算机学院,64,2) 结构变量作为函数的参数,结构变量作为函数的参数时,形参应该声明为结构类型的形参,实参则应该为相同类型的结构变量。 声明函数原型的一般形式为: 存储类型 返回值类型 函数名(形参列表); 形参列表的一般形式是: struct 结构类型名1 a1, , struct 结构类型名n an,其它基本类型的形参声明 即形参a1,an前面都要分别加struct 结构类型名1,, struct 结构类型名n 以表示a1是struct结构类型名1类型的形参,而an是struct 结构类型名n类型的形参。 结构类型名1和结构类型名n可以相同,也可以不同。其
48、它基本类型的形参声明与一般函数相同.,2020/7/10,华中科技大学计算机学院,65,例如,对2个物理量,如果量纲相同,就可以进行物理量大小的相加操作。对应函数原型声明如下: struct motion add_motion( struct motion u,struct motion v ); 形参u和v的类型是struct motion结构类型。add_motion函数的实现见例10.7。 同样的,设有声明: struct motion b=12.5,m/s,c=26.7,m/s,d; 调用add_motion函数的代码为: d=add_motion(b,c);,2020/7/10,华中
49、科技大学计算机学院,66,10.5.2 结构成员或结构变量作为函数的返回值,1结构成员作为函数的返回值 结构成员作为函数的返回值时,函数返回值的类型与结构成员的类型一致。此时要考虑结构成员是基本类型成员,还是结构类型成员两种情况。 如果结构成员的类型是基本类型,则函数声明中返回值部分与普通函数完全一致。 例如,例10.7中,get_motion_size函数返回值是结构变量u的size成员。get_motion_size函数的原型声明为: double get_motion_size( struct motion u); 函数体中用return u.size;返回结构变量u的size成员之值。
50、,2020/7/10,华中科技大学计算机学院,67,对返回嵌套结构中的结构类型的成员,则要注意返回成员的数据类型。 如一个函数fun要返回10.4.3节中struct mul_type结构中的struct date类型的结构成员,并且以struct mul_type结构为形参,则函数原型应该声明为: struct date fun( struct mul_type ); fun函数的一种可能的实现为: struct date fun( struct mul_type t ) t.a.year+; return t.a; ,2020/7/10,华中科技大学计算机学院,68,下面的main函数可以
51、调用fun函数并输出年份成员之值: void main(void) struct mul_type u; u.a=fun(u); printf(%dn,u.a.year); 此时,struct date一定不能在struct mul_type内部声明,即struct date不能是无名结构类型。,2020/7/10,华中科技大学计算机学院,69,2结构变量作为函数的返回值,结构变量作为函数的返回值时,函数原型声明的一般形式为: 存储类型 struct 结构类型名 函数名(形参列表); 如果形参列表的形参的数据类型是基本类型,则形参列表的形式和普通函数形参列表的形式的相同。 如果形参列表的形参的
52、数据类型有结构类型,则形参列表的一般形式为: struct 结构类型名1 a1,struct结构类型名n an,其它基本类型的形参声明 如函数声明: struct date fun( struct mul_type ); 它表示fun函数的形参是struct mul_type类型的形参,返回值的数据类型是struct date类型。,2020/7/10,华中科技大学计算机学院,70,例10.7 通过带有量纲的物理量计算举例说明结构成员作为函数的参数,结构变量作为函数的参数,结构成员作为函数的返回值,以及结构变量作为函数的返回值的使用方法。,#include stdio.h struct mot
53、ion double size; char dimension12; ; /* get_motion函数以结构变量作为函数的返回值 */ struct motion get_motion(void); /* add_motion函数以结构变量作为形参和返回值 */ struct motion add_motion(struct motion u,struct motion v); /* get_motion_size函数以结构变量作为形参,以结构成员作为返回值 */ double get_motion_size( struct motion u); /* add_motion_size函数可以
54、用结构成员作为形参和返回值,也可用于其他double类型形参和返回值 */ double add_motion_size(double,double); int cmp_dimension(char *,char *); void strcpy(char *,char *);,2020/7/10,华中科技大学计算机学院,71,void main(void) struct motion b=12.5,m/s,c=26.7,m/s,d; b=get_motion(); printf(b.size=%lft,b.size); printf(b.dimension is %sn,b.dimension
55、); d=add_motion( b,c ); printf(d.size=%lft,d.size); printf(d.dimension is %sn,d.dimension); d.size=get_motion_size(b); printf(d is %lf%sn,d.size,d.dimension); d.size=add_motion_size(d.size,c.size); printf(d is %lf%sn,d.size,d.dimension); struct motion get_motion(void) /* get_motion函数以结构变量作为函数的返回值 */
56、 struct motion a; printf(input the value of member size and dimensionn); scanf(%lf, ,2020/7/10,华中科技大学计算机学院,72,struct motion add_motion( struct motion u,struct motion v) /* add_motion函数以结构变量作为形参和返回值 */ struct motion a; if(!cmp_dimension(u.dimension,v.dimension) a.size=u.size+v.size; strcpy(a.dimensio
57、n,u.dimension); else printf(dimension of the member is conflicting! cant adding . n); a.size=0; strcpy(a.dimension,); return a; ,2020/7/10,华中科技大学计算机学院,73,double get_motion_size( struct motion u) return u.size; double add_motion_size(double x,double y) return x+y; /* cmp_dimension函数比较两个物理量的量纲。*/ /* 如
58、果两个物理量的量纲相同,返回0;否则返回非0。*/ int cmp_dimension(char *s,char *t) while(*s=*t ,2020/7/10,华中科技大学计算机学院,74,当输入12.5和m/s时,程序的运行结果如下: input the value of member size and dimension 12.5(输入的数据) m/s(输入的数据) b.size=12.500000 b.dimension is m/s d.size=39.200000 d.dimension is m/s d is 12.500000m/s d is 39.200000m/s,2
59、020/7/10,华中科技大学计算机学院,75,10.5.3 结构类型的指针作为函数的参数或函数的返回值,C除了允许结构成员或结构变量作为函数的参数,也允许使用结构类型的指针作为函数的参数,此时结构类型的指针的基类型为结构类型。 至于以指向结构变量中基本类型成员的指针作为形参,其使用方法与一般基本类型指针相同。 使用结构类型的指针的好处是:调用时,只将实参指针的值拷贝到形参指针单元。不需要将实参指针所指向的结构变量拷贝到形参指针所指的形参结构变量中,不需要额外的存储分配。 同时,在函数内部对形参指针的间访操作会影响实参指针所指结构变量的值。因此,结构类型的指针作为函数的参数适合在修改实参指针所指的结构变量值的场合使用。,2020/7/10,华中科技大学计算机学院,76,结构类型的指针作为函数的参数时,函数原型声明的一般形式是: 存储类型 返回值类型 函数名(形参列表); 如果还以结构类型的指针作为函数的返回值,函数原型声明的一般形式是: 存储类型 struct 结构类型名 * 函数名(形参列表); 两种原型中,形参列表的一般形式都为: struct 结构类型名1 *p1, , struct 结构类型名n *pn,其它基本类型的形参
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 肱骨外固定装置去除术后护理查房
- 采购订单更改请求函6篇范文
- 全面性安全管理制度与流程模板
- 企业员工绩效考核体系工具
- 企业工作台功能扩展指南
- 产品品质完好退换承诺书3篇
- 健康生活行为自律承诺书模板5篇
- 江苏省南京师大附中树人校2026届中考英语试题一轮复习高中总复习含解析
- 四川省宜宾市达标名校2025-2026学年初三下学期周练一(2.15)数学试题含解析
- 2026年黑龙江省鸡西市鸡东县重点名校全国初三冲刺考(四)全国I卷英语试题含解析
- 网络安全与信息素养课件
- 国画竹子课件
- 不一样的卡梅拉2-我想有颗星星
- 1999年制干部履历表8k
- 中国普通食物营养成分表一览
- 2023年四川省南充市从“五方面人员”中选拔乡镇领导班子成员201人高频考点题库(共500题含答案解析)模拟练习试卷
- 潜水医学PPT完整全套教学课件
- 水稻病虫害综合防治课件
- 咨询项目突发事件应急预案
- 危急值业务学习(护理)
- 食品生产通用卫生规范宣贯培训课件
评论
0/150
提交评论