资源预览内容
第1页 / 共98页
第2页 / 共98页
第3页 / 共98页
第4页 / 共98页
第5页 / 共98页
第6页 / 共98页
第7页 / 共98页
第8页 / 共98页
第9页 / 共98页
第10页 / 共98页
亲,该文档总共98页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
C+语语言言程程序序设设计计教教程程第第11章章C+输输入入输输出出流流第第5 5章章 构造数据类型构造数据类型主讲:尚明生电子科技大学计算机学院msshanguestc.edu.cn第第5 5章章构造数据类型构造数据类型1.掌握枚举类型的使用;2.深入理解数组的概念,掌握数组应用的一般方法;3.深入理解指针的概念,掌握指针的使用;4.注意指针与数组的区别,掌握多重指针以及指针与数组的混合使用,合理应用动态数组;5.理解字符串的概念,能够灵活使用字符串;6.理解引用的概念,掌握引用型函数参数的用法;7.掌握结构与联合类型的使用,并注意二者的区别。学习目标 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.1枚举类型枚举类型 1. 枚举类型的定义:枚举类型的定义: “枚枚举举”是指将变量所有可能的取值一一列举出来,变量的取值只限于列举出来的常量。 枚举类型的声明的一般形式如下:枚举类型名以及枚举常量为标识符,遵循标识符的取名规则。在定义一个枚举类型时,定义了多个常量,供枚举类型变量取值,称此常量为枚举常量枚举常量。当没给各枚举常量指定值时,其值依次默认为0、1、2、;在定义枚举类型时,也可使用赋值另行指定枚举常量的值。enum 枚举类型名 枚举常量1, 枚举常量2, 枚举常量n;枚举!枚举!C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.1枚举类型枚举类型枚举类型的定义:枚举类型的定义:例1: enum weekday SUN, MON, TUE, WED, THU, FRI, SAT ; 定义了7个枚举常量以及枚举类型weekday。枚举常量具有默认的整数与之对应:SUN的值为0、MON的值为1、TUE为2、SAT为6。例2: enum city Beijing,Shanghai,Tianjin=5,Chongqing; 枚举常量Beijing的值为0,Shanghai的值为1,Tianjin的值指定为5。对于指定值后面的没有指定值的枚举常量,编译器会将前一个常量值加1(下一个整数)赋给它,所以Chongqing的值为6。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.1枚举类型枚举类型枚举类型的定义说明枚举类型的定义说明: :枚举类型定义了以后就可以使用枚举常量、使用用枚举类型来定义变量,定义枚举变量的方法与定义其它变量的方法一样。 例如: enum city city1, city2; city city1, city2;用两种不同方法定义了city1、city2两个枚举类型的变量名。枚举类型变量也可以在定义枚举类型的同时定义例如: enum city Beijing,Shanghai,Tianjin=5,Chongqing city1, city2;在定义枚举类型的同时定义枚举类型变量可以省略枚举类型名例如: enum Beijing,Shanghai,Tianjin=5,Chongqing city1, city2; 在定义变量时,可以顺便给出初值,若不给初值,默认初值为随机的无意义的数。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.1枚举类型枚举类型枚举类型的使用:枚举类型的使用:用枚举类型建立枚举变量后就可以对枚举变量实施赋值以及进行其它运算了,对枚举变量进行赋值,其值要求为同一枚举类型要求为同一枚举类型。否则,在编译时出错。 例如: weekday d1,d2,d3,d4; d1=SUN; d2=6; /错误 d3=Shanghai; /错误 其中对d2所赋之值是整数6,不是枚举常量;可以采用将一个整型值强制转换成同类型的枚举常量赋给枚举变量。枚举常量、枚举类型的变量可可进行算行算术运算、关系运算运算、关系运算。 对枚举类型实施算术、关系运算时,枚举值转换成整型值参加运算,结果为整型值。所以,如果要将结果赋给枚举变量,还要将结果转换成枚举值。 例如: d1=d1+2; /是错误的,因为结果为int型。 需要将它强制转换强制转换成枚举型: d1=(weekday)(d1+2);C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.1枚举类型枚举类型枚举类型的使用:枚举类型的使用: 枚举常量、枚举类型的变量可直接进行各种形式的关系运算可直接进行各种形式的关系运算。 例如: if(city1=3) ; if(city2=Beijing); if(Shanghai=1); if(city1SUN);枚举类型变量不能直接进行输入不能直接进行输入 例如: cind1; /错误C+语语言言程程序序设设计计教教程程第第4章章函函数数F注意注意: :枚举常量是常量,不是变量,所以不能对枚举常量进行赋值。例如:在上例中不能进行赋值Shanghai=Beijing;枚举常量的值不是列举的字符串,其值为整数。编译器对赋给枚举变量的对象(数)进行类型检查,如类型不相符则发出警告。当类型相同,而值超出此类枚举类型枚举常量范围时,也是正常的。123456789101112/*程序名:p5_1.cpp*功能:枚举类型的使用,输入城市代号,输出城市名称*/#includeusingnamespacestd;enumcityBeijing,Shanghai,Tianjin=6,Chongqing;int main()intn;coutInputacitynumber(Beijing-1toexit):n;枚举类型枚举类型定义定义C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型【例【例5-15-1】输入城市代号,输出城市名称。 5.1枚举类型枚举类型131415161718192021222324while(n=Beijing)switch(n)caseBeijing:coutBeijingendl;break;caseShanghai:coutShanghaiendl;break;caseTianjin:coutTianjinendl;break;caseChongqing:coutChongqingendl;break;default:coutInvalidcitynumber!n;return0;运行结果运行结果运行结果运行结果:Inputacitynumber(-1toexit):1Shanghai8Invalidcitynumber!-1 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型枚举类型的使用枚举类型的使用5.1枚举类型枚举类型5.2数组数组 数组:数组: 数组是一组在内存中依依次次连连续续存存放放的、具有同同一一类类型型的数据变量所组成的集合体。其中的每个变量称为数组元素,它们属于同一种数据类型,数组元素用数组名与带方括号的数组下下标标一起标识。数组可以是一维的,也可以是多维的。特点:特点:若干个同类型若干个同类型的数据元素,并且各个数据元素之间存在某种次序关系次序关系。这类数据有一个共同的特点:它们有若干个同类型的数据元素,并且各个数据元素之间存在某种次序关系。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 一维数组定义的一般形式为:一维数组定义的一般形式为: 说明:说明:数组元素的类型可以是void型以外的任何一种基本数据类型,也可以是已经定义过的构造数据类型;数组名是用户自定义的标识符,用来表示数组的名称,代表数组元素在内存中的起始地址,是一个地址常量。常量表达式必须是unsigned int类型的正整数。表示数组的大小或长度,也就是数组所包含数据元素的个数。 是数组下标运算符,在数组定义时用来限定数组元素的个数。数据类型 数组名常量表达式;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注意注意: :数组属于构造数据类型,在使用之前必须先进行类型定义。5.2.1 一维数组定义与使用一维数组定义与使用数组元素的类型可以是void型以外的任何一种基本数据类型,也可以是已经定义过的构造数据类型;例如:下面定义了2个不同类型的数组: int a5; /定义了一个5个元素的整型数组a weekday b10; /定义了一个10个元素的枚举数组b,weekday 为已定义的枚举型。数据类型相同的多个数组可以在同一条语句中予以定义。例如: int a110, a220; /同时定义了两个整型数组 数据类型相同的的简单变量和数组也可以在一个语句中定义。例如:int x, a20; /同时定义了一个整型变量和一个整型数组C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 数组定义之后,系统会将从内存中为其分配一一块块连连续续的的存存储储空空间间,从第1个数据元素开始依依次次存存放放各个数组元素。例如,定义的数组a其内存排列(分配)示意图如图5-1所示。 例如: int a5; /定义了一个5个元素的整型数组a C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 一维数组初始化:一维数组初始化:是指在定义数组的同时给数组中的元素赋值。其一般语法形式为:其一般语法形式为: 初值1,初值2, 初值n称为初值表,初值之间用逗号,分隔, 所有初值用 括起来。初值可以是一个变量表达式变量表达式,初值与数组元素的对应关系是:初值i给数组第i个元素;所以,初值个数n不能超过数组的大小。若初值表中初值个数(项数)小于数组的大小,则未指定值的数组元素被赋值为0 0;但初值表中项数不能为0。例如: weekday b10=MON,WED,FRI;当对全部数组元素赋初值时,可可以以省省略略数数组组的的大大小小,此时数组的实际大小就是初值列表中初值的个数。例如: char str = a, b, c, d, e ; /数组str的实际大小为5。在函数中定义数组时,如果没有给出初值表,数组不被初始化,其数组元素的值为随机值随机值;在函数外定义数组如果没有初始化,其数组元素的值为0。数组初值表的可以用一个逗号逗号结尾,其效果与没有逗号一样。 数据类型 数组名 常量表达式 =初值1, 初值2, 初值n;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 对一维数组实施的存取操作有两类:存存取取数数组组元元素素与读读取取数数组组元元素素的的地地址址。数组元素是通过数组名及下标来标识的,这种带下标的数组元素也称为下标变量下标变量,下标变量可以象简单变量一样参与各种运算。存取一维数组元素的一般语法形式为: 说明:说明:下标表达式可以是变量表达式变量表达式,用来标识数组元素;不同于数组定义时用来确定数组长度的常量表达式。当定义了一个长度为n的一维数组a,C+规定数组的下标从从0 0开始开始,依次为0、1、2、3、n-1。对应的数组元素分别是a0、a1、an-1,因此下标表达式的值要在0,n-1范围内。例如: a1+2=100; / 将数组a的第4个元素赋值100。 数组名 下标表达式; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 【例【例5-25-2】学生成绩排序。分析分析:学生成绩由键盘输入,当输入一个负数时,输入完毕。 采用直观的“选择排序法选择排序法”进行排序,基本步骤如下: 将a0依次与a1an-1比较,选出大者与a0交换;最后a0为a0an-1中最大者; 将a1依次与a2an-1比较,选出大者与a1交换;最后a1为a1an-1中最大者; 同理,从i=2到i=n-1, 将ai依次与ai+1an-1比较,选出较大者存于ai中。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型123456789101112131415161718/*p5_2.cpp*数组应用-选择排序*/#includeusingnamespacestd;intmain()constintMaxN=5;intn,aMaxN,i,j;for(n=0;nan;/输入数组元素if(an0)break;for(i=0;in;i+)coutai,t;coutnnendl;数组定义数组定义数组使用数组使用C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型1920212223242526272829303132 /对数组元素逐趟进行选择排序for(i=0;in-1;i+)for(j=i+1;jn;j+)/从待排序序列待排序序列中选择一个最大的数组元素if(aiaj)intt;t=ai;/交换交换数组元素ai=aj;aj=t;for(i=0;in;i+)coutai“,t”;/显示排序结果return0;运行结果运行结果运行结果运行结果:80909570-195 90 80 70C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.1 一维数组定义与使用一维数组定义与使用 4. 4. 数组的地址数组的地址数组元素的地址通过数组名通过数组名来读取,其格式如下: 由于其地址不不是是实实际际的的地地址址值值,称这个地址表达式为符符号号地地址址表表达达式式。例如:一维数组元素a5的符号地址表达式为a+5。若a是一个int型数组,数组的符号地址表达式a+n所表达的地址是第n+1个元素an的地址,代表的实际地址值为:a+n*sizeof(int) 而不是:a+n。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型数组名+整型表达式;5.2.1 一维数组定义与使用一维数组定义与使用 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F使用数组要使用数组要注意注意: :在使用数组时最常犯的错误是数组元素越界,包括上标越界和下标越界。上标越界是指数组元素的访问地址值超过了数组的起始地址;下标越界是指数组元素的访问地址越过了数组中最后一个数组元素的地址。对于这种错误,编译器无法知道,往往在运行时出错。因此在程序设计时应格外注意。数组名是一个地址常量,不能作为左值(赋值的目标)。因此,不能将一个数组整体拷贝给另外一个数组。 例如: int a5,c5,i; a=c;/错误! 正确的方法是将对应的元素进行拷贝,见下列程序段: for(i=0;i5;i+) ai=ci; /将数组c中元素的值拷贝到数组c的对应元素中在函数中,可以将一个一维数组作为函数的形式参数,用来接受一个一维数组传递过来的地址。 5.2.2 二维数组的定义与使用二维数组的定义与使用 二维数组的定义的一般形式为: 其中:常量表达式1为第1维的元素的个数,常量表达式2为第2维元素的个数。二维数组amn是以长度为n的一维数组为元素的数组,因此,等价于如下定义方式:例如: int M23; 定义了一个整型二维数组M,数组M也可以用下列方式定义: typedef int M13; / 定义了一个一维整型数组M1; M1 M2; / 以M1为类型定义数组M数据类型 数组名常量表达式2常量表达式1; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型typedef 数据类型 一维数组名常量表达式1;一维数组名 二维数组名常量表达式2;5.2.2 二维数组的定义与使用二维数组的定义与使用 如果一维数组描述排列成一一行行的数据,那么,二维数组则描述若干行这样的数据。因此,二维数组可以看作是数学上的一个矩阵。第1维元素个数为矩阵的列数,第2维元素个数为矩阵的行数。 二维数组的定义格式可以写成: 定义一个二维数组后,系统为它分配一块连续连续的内存空间。 二维数组amn占内存空间的计算公式为: 数据类型 数组名行数列数; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型sizeof(数组名);或 m*sizeof(a0); 或 m*n*sizeof(数据类型)5.2.2 二维数组的定义与使用二维数组的定义与使用 既然一个二维数组是由若干个一维数组排列构成,二维数组在内存中的排列顺序为:先顺序排列每个一维元素先顺序排列每个一维元素, ,构成一维数组构成一维数组;再将各个一维数组顺序排列,构成二维数组。 int M23的排列顺序为:先先将3个int元素排列组成2个一维数组M0, M1。 M0:M00,M01,M02 M1:M10,M11,M12 再再将2个一维数组排成一个二维数组。 M: M0, M1 数组M在内存中的排列图如图所示。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.2 二维数组的定义与使用二维数组的定义与使用 二维数组的初始化二维数组的初始化 :其中初值表具有两种形式:嵌套的初值表,线性初值表。 (1)(1)嵌套初值表嵌套初值表以二维数组Mmn为例,嵌套初值表的格式为: 嵌套初值表由一维初值表嵌套构成,各层构成规则与一维数组的初值表相同。 例如: intM34=1,2,3,4,3,4,5,6,5,6,7,8;/M数组元素被全部初始化inta23=1,0,0,1;/初始化了部分数组元素intb3=1,2,3,;/初始化了全部数组元素 intd3=1,3,5,5,7,9;/初始化了全部数组元素,省略了高维元素个数数据类型 数组名 常量表达式2常量表达式1=初值表; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型M的初值表=M0初值表,M1初值表,Mm-1初值表Mi初值表=Mi0初值表, Mi1初值表,Min-1初值表;i从0到m-1;5.2.2 二维数组的定义与使用二维数组的定义与使用(2 2)线形初值表)线形初值表线形初值表与一维数组的初值表相同,初值表的项数不超过各维元素个数的乘积(总元素个数)。数组元素按内存排列顺序依次从初值表中取值,下列各数组使用了线形初值表,结果与使用嵌套初值表相同。 例如: intM34=1,2,3,4,3,4,5,6,5,6,7,8;/M数组元素被全部初始化inta23=1,0,0,0,1,1;/初始化了全部数组元素,一部分元素未给初值intb3=1,0,0,0,0,0;/初始化了全部数组元素,省略了高维元素个数当使用线形初值表而省略高维元素个数时,高维元素个数为: 例如: int b 3=1,0,0,0;/高维元素个数为2C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型 向上取整数(线形初值表项数/低维元素个数) 5.2.2 二维数组的定义与使用二维数组的定义与使用(3 3)二维数组的存取)二维数组的存取 存取维数组元素的格式为: 说明:说明:行下标表达式与列下标表达式的值同样从0开始,aij表示数组的第i+1行、第j+1列的元素。由于数组元素是变量,可以对其进行各种各种操作。数组元素如果定义数组amn, 即数组第1维大小为n, 第2维大小为m。aij的排列位置与在内存中的地址计算公式如下: 例如: a, a0: 为数组a的起始地址, 即a00的地址; ai+j: 为数组的第i+1行的第j+1元素的地址,即aij的地址; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型数组名 行下标表达式 列下标表达式aij的排列位置=第1维大小n*i+j+1;aij的地址=a的起始地址+(第1维大小n*i+j)*sizeof(数据类型)1234567891011121314151617181920/*p5_3.cpp*求学生多门功课的总分,并求所有学生各门功课的平均分*/#includeusingnamespacestd;int main()constintMaxN=100,CourseN=5;intn,scoreMaxNCourseN+1=0;floataverCourseN+1=0;for(n=0;nMaxN;n+)/输入学生成绩for(intj=0;jscorenj;if(scoren00)break;/输入-1,结束输入for(inti=0;in;i+)/计算每个学生的总分for(intj=0;jCourseN;j+)scoreiCourseN=scoreiCourseN+scoreij;二维数组定义二维数组定义并初始化并初始化二维数组使用二维数组使用C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型212223242526272829303132333436363738for(intj=0;jCourseN+1;j+)/计算每门课程的平均分for(inti=0;in;i+)averj=averj+scoreij;averj=averj/n;for(i=0;in;i+)/输出每个人的成绩与总分for(intj=0;jCourseN+1;j+)coutscoreijt;coutendl;cout-endl;for(i=0;iCourseN+1;i+)/输出每门功课的平均分coutaverit;coutendl;return0;运行结果运行结果运行结果运行结果:707172737482838485869293949596-10000707172737436082838485864209293949596470-81.3333 82.3333 83.3333 84.3333 85.3333 416.667C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.3 多维数组多维数组 (1 1)三维以及高于三维的数组称为多维数组)三维以及高于三维的数组称为多维数组 多维数组的定义与二维数组类似,可以一次定义,也可以逐步由低维数组定义。 例如: int b234; /定义了一个三维数组 也可用下列方式步定义: typedef int B134; B1 b2; 多维数组在内存的排列方式同样是先排低维数组,由低向高依次排列由低向高依次排列。如:b234的排列顺序为: b00:b000,b001,b002,b003 b0 b01:b010,b011,b012,b013b b02:b020,b021,b022,b023 b10:b100,b101,b102,b103 b1 b11:b110,b111,b112,b113 b12:b120,b121,b122,b123C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.3 多维数组多维数组 (2)多维数组的初始化与存取)多维数组的初始化与存取多维数组的初始化形式与二维数组类似:有嵌套初值表、线性初值表两种形式。使用线性初值表初始化时,数组元素按内存排列顺序依次从初值表中取值。对多维数组进行存取包括对数组元素的存取和对数组元素的地址的读取,当一个多维数组的下标数与维数相同时,为对数组元素的存取。当下标个数小于维数时表示的是一个地址,表示地址时,下标也不能越界。 如:下列都是b234的地址表达式。 b1; /b100的地址; b2; /错误,下标越界; b0+1; /与b01相同,b010的地址。 b12; /b120的地址 b12+4; /b124的地址,但数组b中没有b124这个元素, 故指向了其它地方。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型123456789101112131415161718/*5_4.cpp*多维数组的各种地址表达式*/#includeusingnamespacestd;intmain()constintK=3,M=4,N=5;intk=2,m=3,n=4;shortintbKMN;coutAddofb:&b=&bendl;coutb=bendl;cout&b000=&b000endl;coutAddofbk:&bk=&bkendl;coutbk=bkendl;coutb+k=(b+k)endl;cout&b0+k=(&b0+k)endl;cout&bk00=&bk00endl;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型1920212223242526272829303132coutAddofbkm:&bkm=&bkmendl;coutbkm=bkmendl;coutbk+m=(bk+m)endl;cout&b00+k*M+m=(&b00+k*M+m)endl;cout&bkm0=&bkm0endl;cout&b00+(k*sizeof(b0)/sizeof(b00)+m=;cout(&b00+(k*sizeof(b0)/sizeof(b00)+m)endl;coutAddofbkmn:&bkmn=&bkmnendl;coutbkm+n=(bkm+n)endl;cout&b000+k*M*N+m*N+n=(&b000+k*M*N+m*N+n)endl;cout&b000+(sizeof(b0)*k+sizeof(b00)*m)/sizeof(b000)+n=;cout(&b000+(sizeof(b0)*k+sizeof(b00)*m)/sizeof(b000)+n)endl;return0;运行结果运行结果运行结果运行结果:Add of b: &b=0012FEF0Add of b: &b=0012FEF0 b=0012FEF0 b=0012FEF0 &b000=0012FEF0 &b000=0012FEF0Add of bk: &bk=0012FF40Add of bk: &bk=0012FF40 bk=0012FF40 bk=0012FF40 b+k =0012FF40 b+k =0012FF40 &b0+k=0012FF40 &b0+k=0012FF40 &bk00=0012FF40 &bk00=0012FF40Add of bkm: &bkm=0012FF5EAdd of bkm: &bkm=0012FF5E bkm=0012FF5E bkm=0012FF5E bk+m =0012FF5E bk+m =0012FF5E &b00+k*M+m=0012FF5E &b00+k*M+m=0012FF5E &bkm0=0012FF5E &bkm0=0012FF5E &b00+(k*sizeof(b0)/sizeof(b00)+m=0012FF5E &b00+(k*sizeof(b0)/sizeof(b00)+m=0012FF5EAdd of bkmn: &bkmn=0012FF66Add of bkmn: &bkmn=0012FF66 bkm+n=0012FF66 bkm+n=0012FF66 &b000+k*M*N+m*N+n=0012FF66 &b000+(sizeof(b0)*k+sizeof(b00)*m)/sizeof(b000)+n=0012FF66C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.4数组与函数数组与函数 数数组组名名是一个地址,不能当作一个左值,但是可以作为函数的形参,接受实参传送来的地址。当形参接受实参传送来的地址后,形参数组与实参共共享享内内存存中中的的一一块块空空间间。函数体通过形参对数组内容的改变会直接作用到实参上。数组名作为形参是数组应用的一个重要方面。注意注意: (1)(1)使用数组名传递地址时,虽然传递是地址,但形参与实参的地址 (数组)类型应一致类型应一致。 (2)(2)形式参数中数组元素个数没有给定没有给定,因此,在函数体中,对数组存取的下标可以为任意值而不会出现编译错误。但是,当这个下标超过超过了实参数组的元素个数范围时,存取的就不是实参数组中的内容了。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型123456789101112131415161718192021/*5_5.cpp*利用对一个多维数组的某列排序的函数,*将学生某门功课的成绩分班级排序*/#includeusingnamespacestd;constcol=5;enumdirAsc,Des;void sort(int acol, int n, int Cn, dir D)/排序inttcol;/用于暂存一行数据for(inti=0;in-1;i+)for(intj=i+1;jn;j+)/从待排序序列中选择一个最大(小)的数组元素if(aiCnajCn&D=Asc)memcpy(t,ai,sizeof(t);/交换数组行memcpy(ai,aj,sizeof(t);memcpy(aj,t,sizeof(t);C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型数组作为函数形式参数数组作为函数形式参数 22232425262728293031323334353637383940414243int main()constCourseN=5;intn,scoreCourseN=20060101,1,82,86,0,20060203,2,80,80,0,20060204,2,86,90,0,20060205,2,90,83,0,20060102,1,75,86,0;n=sizeof(score)/sizeof(score0);for(inti=0;in;i+)/计算每个学生的总分for(intj=2;jCourseN-1;j+)scoreiCourseN-1=scoreiCourseN-1+scoreij;sort(score,n,4,Des);/按总分降序排序sort(score,n,1,Asc);/按班号的升序排序for(i=0;in;i+)/输出每个人的成绩与总分for(intj=0;jCourseN;j+)coutscoreijt;coutendl;return0;运行结果运行结果运行结果运行结果:20060101200601011 18282868616816820060102200601021 17575868616116120060204200602042 28686909017617620060205200602052 29090838317317320060203200602032 280808080160160 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型数组作为函数形式参数数组作为函数形式参数 5.2.5字符数组与字符串字符数组与字符串 存放字符型数据的数组称为字字符符数数组组。字符数组也分为一维数组和多维数组。 前述的数组的定义及初始化同样适用于字符数组,除此以外,C+对字符数组的初始化还可以使用字符串形式。1.1.用字符进行初始化用字符进行初始化 例如: chars1=C,h,i,n,a;chars24=H,o,w,a,r,e,y,o,u;2.用字符串进行初始化用字符串进行初始化例如: chars3=China;chars44=how,are,you;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型3. 3. 字符数组的使用字符数组的使用 字符数组也是数组,我们同样可以通过数组名及下标引用数组中的元素。 为方便对字符与字符串的处理,C+提供了许多专门处理字符与字符串的函数,这些函数原型在各自的头文件中定义。 下表列出了常用的字符与字符串处理函数的调用方法与功能简介,函数原形与详细的功能可以从C+编译器的帮助文档中获得。函数的用法函数的用法函数的用法函数的用法函数的用法函数的用法strlen(字符串)返回字符串的长度(不包括0)Cstringstrset(字符数组,字符C)将字符数组中的所有字符都设为指定字符C,并以0结尾strlwr(字符串)将字符串中的所有字符转换成小写字符strupr(字符串)将字符串中的所有字符转换成大写字符strcmp(串s1,串s2)比较两个字符串的大小,即按从左到右的顺序逐个比较对应字符的ASCII码值。若s1大于s2,返回1;若s1小于s2,返回-1;若s1等于s2,返回0。串s1、s2可以是字符串常量C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.5字符数组与字符串字符数组与字符串常用字符与字符串处理函数常用字符与字符串处理函数函数的用法函数的用法函数的用法函数的用法函数的用法函数的用法strcpy(串s1,串s2)将字符串s2拷贝到s1所指的存储空间中,然后返回s1。其中,串s2可以是字符串常量Cstringstrcat(串s1,串s2)返回字符串的长度(不包括0)Ctypetoupper(字符)将字符数组中的所有字符都设为指定字符C, 并以0结尾tolower(字符)将字符串中的所有字符转换成小写字符Cstdlibatoi(字符串)将字符串中的所有字符转换成大写字符atol(字符串)比较两个字符串的大小,即按从左到右的顺序逐个比较对应字符的ASCII码值。若s1大于s2,返回1;若s1小于s2,返回-1;若s1等于s2,返回0。串s1、s2可以是字符串常量 atof(字符串)将字符串s2拷贝到s1所指的存储空间中,然后返回s1。其中,串s2可以是字符串常量C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.2.5字符数组与字符串字符数组与字符串常用字符与字符串处理函数常用字符与字符串处理函数12345678910111213141516171819/*p5_6.cpp*字符串排序与查找*/#includeusingnamespacestd;constNameLen=20;void order(char nameNameLen,int n)/字符串排序char tempNameLen;for(inti=0;in-1;i+)/选择排序for(intj=i+1;j0)/比较两个字符串的大小 strcpy(temp,namei);/字符串交换strcpy(namei,namej);strcpy(namej,temp);C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型2021222324252627282930313233343536373839404142434445intfind(charnameNameLen,intn,charsearchnameNameLen)for(inti=0;i0)/未找完,但找不到,返回0return0;return0;/找完,找不到,返回0intmain()charNameTabNameLen=GongJing,LiuNa,HuangPin,ZhouZijun,LianXiaolei,ChenHailing,CuiPeng,LiuPing;charsearchnameNameLen;intn=sizeof(NameTab)/NameLen;order(NameTab,n);for(inti=0;in;i+)/输出排序后的各姓名couti+1tNameTabiendl;coutsearchname;if(n=find(NameTab,n,searchname)coutPosition:nendl;elsecoutNotfound!endl;return0;1ChenHailing1ChenHailing2CuiPeng2CuiPeng3GongJing3GongJing4HuangPin4HuangPin5LianXiaolei5LianXiaolei6LiuNa6LiuNa7LiuPing7LiuPing8ZhouZijun8ZhouZijunInputthesearchingname:LiuPingInputthesearchingname:LiuPingPosition:7Position:7C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针 指针是C+语言最重要特性之一,也是C+的主要难点。 指针提供了一种较为直观的地址地址操作的手段,正确地使用指针,可以方便、灵活而有效地组织和表示复杂的数据。 指针在C+程序中扮演着非常重要的角色,从某种程度上而言,如果不能深刻的理解深刻的理解指针的概念,正确而有效的掌握指针,就不可能真正学好C+,但是指针也是我们最容易产生困惑并导致程序出错的原因之一。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针1. 1. 地址与指针地址与指针地址:地址: 当定义一个变量后,内存中将会划出一块由若干个存储单元组成的区域,用于保存该变量的数据。在内存里每个存储单元都有各自的编号,称为地址地址。指针: 在C+中,提供了指针指针类型,它是一种用于存放内存单元地址的变量类型,地址就存储在这种指针类型的变量中。正因为指针变量存储的是地址,用它来指明内存单元,所以形象地称这种地址变量为指针指针。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针2. 2. 指针变量的定义指针变量的定义 每存储一个地址,就要定义一个指针变量。定义指针变量的格式如下: 数据类型是指针变量所指向对象的数据类型,它可以是基本数据类型,也可以是构造数据类型以及void 类型。 变量名是用户自定义的标识符。 *表示声明的变量是一个指针变量,而不是普通变量。 例如: int*ip;/定义了一个int型的指针变量ipfloat*fp;/定义了一个float型指针变量fptypedefintA10;A*ap;/定义了一个A类型的指针变量apsizeof(ip)=sizeof(fp)=sizeof(ap)=4;数据类型 * 变量名; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针 3 3指针的初始化与赋值指针的初始化与赋值 定义了一个指针,只是得到了一个用于存储地址的指针变量。若指针变量既没有初始化,也没有赋值,其地址值是一个随机的数。 (1)不要将一个非地址常量、变量以及无意义的实际地址赋给指针变量。如:int*p=100;/错误,100是一个int型常量,不是一个地址常量。int*p=(char*)100;/危险!100是一个无意义的实际地址,可能指向危险区域。(2)可以使用一个已初始化的指针去给另一个指针赋值,但类型必须一致如果不一致,可进行强制类型转换。char*p=NULL;int*ip=(int*)p+100;/将char型指针强制转化成int型指针。(3)对于基本数据类型的变量、数组元素我们可以使用取地址运算符&来获得它们的地址,但是也只有类型一致才能赋值。inta10;/定义int型数组int*i_pointer=a;/定义并初始化int型指针(4)有一种特殊的void类型指针,可以存储任何的类型地址;但将一个void类型的地址赋值给非void类型的指针变量,要使用类型强制转换。voidv;/错误,不能定义void类型的变量void*vp;/定义void类型的指针 数据类型 *指针变量名=初始地址表达式; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针4 4指针运算指针运算 指针变量存放的是地地址址,因此指指针针的的运运算算实实际际上上就就是是地地址址的的运运算算,但正是由于指针的这一特殊性,使指针所能进行的运算受到了一定的限制。指针通常进行下列几种运算:赋值运算、取值运算、算术运算、相减运算、比较运算。 (1 1)* * 和和& &运算运算 * *称为指针运算符指针运算符。出现在数据定义语句中时,* 在数据类型与变量之间,是一个二二元运算符元运算符,用来定义指针变量;出现指针变量表达式左边左边时,是一个一元运算符,表示访问指针所指对象的内容所指对象的内容。例如:inta4=1,2,3;int*ip=&a2;cout*ip;/输出ip指向单元的内容,内容为整型数3*ip=100;/将100赋给a2;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针(2)指针与整数的加减运算)指针与整数的加减运算 指针的加减运算与普通变量的加减运算不同,由于指针存储的是变量的内存地址,指针加上或减去一个整数n,表示指针从当前位置向后或向前移动n个sizeof(数据类型)长度的存储单元。因此对于不同的数据类型,n的实际大小就不同。 例如程序段:intb234;typedefcharA10;int*p1=b10;int*p2=(int*)b1;int*p3=(int*)(b+1);double*pd=(double*)p3;A*pa=(A*)p3;coutp1,p2,p3,pd,paendl;coutp1+1,p2+1,p3+1,pd+1,pa+1endl;运行结果运行结果运行结果运行结果:0013FF80, 0013FF80, 0013FF80, 0013FF80, 0013FF800013FF80, 0013FF80, 0013FF80, 0013FF80, 0013FF800013FF84,0013FF84,0013FF84,0013FF88,0013FF8A C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针(3 3)指针自增、自减运算)指针自增、自减运算 指针的自增、自减运算是指针加减运算的特例。指针的自增或自减表示指针从当前位置向后或向前移动sizeof(数据类型)长度的存储单元。 例如:程序段:int*p,*q,a=5;p=&a;p+;/指针p后移4个字节*p+;/先读取p指向的变量a的值5,然后使指针p后移4个字节(*p)+;/读取p指向的变量a的值,然后使p指向的变量a自增1*+p;/先使指针p后移4个字节,然后读取p指向的变量的值+*p;/将p指向的变量a自增1*q+=*p+;/这是一种常用的表达式,依次执行:*q=*p,q+,p+(4 4)两指针相减)两指针相减 当两个指针指指向向同同一一数数组组时时,两个指针的相减才才有有意意义义。两个指针相减的结果为一整数,表示两个指针之间数组元素的个数。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3 指针指针(5 5)两个指针的比较运算)两个指针的比较运算 两个指针的比较一般用于下列两种情况:一是比较两个指针所指向的对象在内存中的位置关系位置关系;二是判断指针是否为空指针空指针。 5 5voidvoid类型指针类型指针 指向void类型的指针是一种不不确确定定类类型型的指针,它可可以以指指向向任任何何类类型型的的变变量量。实际使用void型指针时,只有通过强强制制类类型型转转换换才能使void型指针得到具体变量的值。在没有转换前没有转换前void型指针不能不能进行指针的算术运算。 例如: void*vp;/定义了一个void型指针vpinti=6,*ip;vp=&i;/vp指向整型变量icout“i=”*vpendl;/错误couti=*(int*)pendl;ip=(int*)vp;/ip指向vp指向的变量icouti=*ipendl;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.2指针与字符串指针与字符串 字符型指针:字符型指针: 用于存放字符型变量的地址,而字字符符串串的的本本质质是是以以00结结尾尾的的字字符符数数组组,一个字符型指针存储了字符数组的第一个元素的地址,也就存储了字符串的地址,这个指针就指向了字符串。 在定义一个字符数组时,可以将一个字符串常量作为初值,但将字符串常量作为初值赋给字符数组和将字符串常量作为初初值值赋给字符指针变量,二者的含义是不同的。例如: charstr5=abcd;char*p_str=abcd;在上述字符串定义有下列不同: (1) (1) 字符数组str5被赋值为“abcd”,因此,数组str的五个数组元素的值分别为 字符a、b、c、d和0。字符指针p_str被赋值为“abcd”,则意味着 指针指针p_strp_str的值的值为字符串常量abcd的第一个字符第一个字符a在内存中的地址。 (2) (2) 字符指针p_str比str多多分分配配了了一一个个存存储储地地址址的的空空间间,用于存储字符串的首地 址。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.3 5.3.3 指针与数组指针与数组 1.1.使用指针操作符使用指针操作符* *存取数组存取数组 指指针针的的加加减减运运算算的的特特点点使得指针操作符特别适合处理存储在一一段段连连续续内内存存空空间间中的同类型数据。这样,使用指针操作符来对数组及其元素进行操作就非常方便。(1) (1) 一维数组的指针操作一维数组的指针操作 当定义数组一维数组T aN (T为类型),下式为存取数组元素ai的等效方式: *(a+i); 而a+i为ai的地址。(2) (2) 多维数组的指针操作多维数组的指针操作 对于多维数组,使用指针同样可以灵活访问数组元素。若定义数组T bKMN, 下式为存取数组元素aijk的等效方式等效方式: 例如: *(*(*(b+i)+j)+k); 其中:*(*(b+i)+j)+k为bijk的地址,即&bijk; *(*(b+i)+j)为bij0的地址,即bij; *(b+i)为bi00的地址,即bi; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.3 5.3.3 指针与数组指针与数组 2.2.指针数组指针数组 指针数组是以指指针针变变量量为为元元素素的数组,指针数组的每个元素都是同一类型的指针变量。 在指针数组的定义中有两个运算符:*和 ,运运算算符符 的的优优先先级级高高于于* *,所以*pN等价于*( pN),p N表示一个数组,而*表示数组元素为指针变量。例如: int*p_a5; 定义了一个指针数组,其中有5个数组元素,每个数组元素都是一个int类型的指针。 F注意注意: :对指针数组的存取同样可以使用指针方式、数组方式、以及指针与数组结合的方式。一维指针数组与二维指针数组对应,可采用存取二维数组的方式存取。指针数组的每一个元素都是一个指针,因此必须先赋值先赋值,后引用后引用。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.3 5.3.3 指针与数组指针与数组 3 3)数组指针)数组指针 数组指针是指向数组的指针。 虽然运算符 的优先级高于*,但是,在数组指针的定义式中,(* 指针名)改变了这种优先级,它表明定义的首先是一个指针,然后才是什么类型的指针。例如:int(*a_p)5;等效于下列定义方式:typedefintI_A5;I_A*a_p;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.4 5.3.4 多重指针多重指针 如果已经定义了一个指针类型,我们再定义一个指针,用于指向已经定义的指针变量,后面定义的指针变量就是一个指向指针的指针变量,简称指指向向指指针的指针针的指针,这样的指针也称二重二重( (级级) )指针指针。 三重及以上三重及以上的指针统称为多重指针多重指针。例如: int*pp; 定义了一个二级指针变量,等效于下列定义方式: typedefint*P;P*p; 二级指针常用来指向一个指针数组。例: inta23=1,2,3,4,5,6;/声明并初始化二维数组int*p_a3;/声明整型指针数组p_a0=a0;/初始化指针数组元素p_a1=a1;int*pp;pp=p_a;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.4 5.3.4 多重指针多重指针注意:注意:在使用二级指针时经常容易犯两类错误。(1 1)类型不匹配)类型不匹配 例如: pp=a;/错误,因为pp是一个int*型变量,a是一个int23型的地址pp=&a;/错误,pp是一个int*型变量,&a是一个(*)int23型的地址pp=&a0;/错误,pp是一个int*型变量,&a0是一个(*)int3型的地址(2)(2)指针没有逐级初始化指针没有逐级初始化 例如: inti=3;int*p2;*p2=&i;*p2=5;cout*p2; 虽然上述程序段编译、连接均没有错误,但运行时出错。其原因在于int *p2;只是定义了一个指针变量,变量中的内容(地址)是一个无无意意义义的的地地址址,而*p2=&i是对无意义的内存单元赋值,这样是错误与危险的。正确的作法是从第一级指针开始,逐级初始化从第一级指针开始,逐级初始化。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.4 5.3.4 多重指针多重指针3)逐级初始化多级指针逐级初始化多级指针 例: int i=3; int *p2; int *p1; p1=&i; /初始化一级指针 p2=& &p1; /初始化一级指针 *p2=5; /通过指针给变量i赋值 cout*p2; /结果为5 上述两个二级指针在内存中的分布如右图所示。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.4 5.3.4 多重指针多重指针当一个二级指针指向一个指针数组后,对数组元素的存取可以使用指针方式、数组方式、混合方式:例如: pij;/存取数组元素aij的数组方式;*(*(p+i)+j);/存取数组元素aij的指针方式;*(pi+j);/存取数组元素aij的混合方式;一般而言,二重指针就足够使用了,三重指针使用场合就很少了,使用多重指针同样要:F注意注意: :不管是多少重指针,定义后,只建立了一个指针变量只建立了一个指针变量,分配一个指针变量的空间。要初始化多重指针初始化多重指针,要从第一层开始,逐步向高层进行逐步向高层进行。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.5 5.3.5 动态内存分配动态内存分配 在C+中,动态内存分配技术可以保证程序在运行过程中根据实际需要申请适量的内存,使用结束后还可以释放。C+通过new运运算算和delete运运算算来实现动态内存分配。1.new运算运算new运算的作用是按指定类型和大小动态的分配内存。基本语法形式为:其中:数据类型可以是基本数据类型,也可以是用户自定义的复杂数据类型。new运算符在堆(内存)中创建一个由类型名指定类型的对象,如果创建成功,返回对象的地址;否则返回空指针NULL。初值列表给出被创建对象的初始值。由于返回的是地址,所以要用事先定义一个类型相同的指针变量来存储这个地址。指针变量指针变量=new类型名类型名(初值列表初值列表);C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.5 5.3.5 动态内存分配动态内存分配1)new创建指定类型对象创建指定类型对象例:int*ip;ip=newint(5);/ip指向1个初值为5的int型对象也可以使用一条语句定义:int*ip=newint(5);C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F说明说明: : 首先定义了一个整型指针ip; 然后申请内存,创建一个int型数据对象,并将该数据对象初始化为5; 最后返回创建的数据对象的地址,存入ip。5.3.5 5.3.5 动态内存分配动态内存分配2)new创建动态数组时创建动态数组时 使用new运算可创建一个数据对象,也可以创建同类型的多个对象-数组。由于数组大小可以动态给定,所创建的对象称为动动态态数数组组。new创建动态数组时,需要给出数组的结构说明。 其语法格式如下:其中:下标表达式与数组初始化时的常量表达式不同,可以是变量表达式。用new申请失败时,返回NULL。申请一个动态数组,往往需要较大的空间,因此,在程序中需要对new的返回值进行判断,看是否申请成功。例:int*pa;pa=newint5;/ip指向5个未初始化的int型数据对象的首地址C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型指针变量指针变量=new类型名类型名下标表达式下标表达式;5.3.5 5.3.5 动态内存分配动态内存分配3)new创建多维数组创建多维数组 使用new也可创建多维数组,其语法形式如下: 其中:当用new创建多维数组时,只有下标表达式1可以任意结果是正整数的表达式,而其它下标表达式必须是值为正整数的常量表达式。如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,它是一个T类型数组的指针,而不是T类型指针。数组元素的个数为除最左边一维(最高维)外各维下标表达式的乘积。例:int*pb;pb=newint345;/错误,new操作产生的是指向一个int45的二维int/型数组的指针int(*pb)45;pb=newint345;/正确,针pb既可以作为指针使用,也可以像一个/三维数组名一样使用C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型指针变量指针变量=new类型名类型名T下标表达式下标表达式1下标表达式下标表达式25.3.4 5.3.4 多重指针多重指针2、delete运算运算当程序不再需要由new分配的内存空间时,可以用delete释放这些空间。其语法格式为:如果删除的是动态数组,则语法格式为:其中:括号表示用delete释放为多个对象分配的地址,中不需要说明对象的个数。不管建立的动态数组是多少维,释放的格式都是一样。对于例分配的空间,释放语句如例:deleteip;deletepa;deletepb;delete指针变量名;指针变量名;delete指针变量名;指针变量名;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型123456789101112131415161718192021/*p5_7.cpp*动态二维矩阵*/#includeusingnamespacestd;int main()intm,n;int*dm;coutmn;dm=new int * m;/建立m个指针,存储m行for(inti=0;im;i+)/为每行分配n个空间if(dmi=new int n)=NULL)exit(0);for(i=0;im;i+)/输入矩阵元素for(intj=0;jdmij;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型2223242526272829303132for(i=0;im;i+)/输出输出矩阵元素for(intj=0;jn;j+)coutdmijt;coutendl;for(i=0;im;i+)/释放m个指针指向的空间;delete dmi;delete dm;/释放m个指针return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:inputmatrixsizem,ninputmatrixsizem,n:2323 123123 456456 123123456456 F注意注意: :各用new运算符申请分配的内存空间,必须用必须用deletedelete释放; delete作用的指针必须是由new分配内存空间的首地址;对于一个已分配内存的指针,只能用只能用deletedelete释放一次释放一次; new和delete运算实现了堆空间的动态分配,它在带来方便的同时也潜伏了可能的隐患:使用new进行内存分配之后,忘记了使用delete运算进行内存回收,即“内存泄露内存泄露”,如果程序长时间运行,则有可能因内存耗尽而使系统崩溃, 以对new和delete要养成配对使用配对使用的良好习惯。 123456789101112131415/*程序名:p5_8.cpp*功能:动态创建多维数组*/#includeusingnamespacestd;intmain()float(*p)34;inti,j,k;p=newfloat234;for(i=0;i2;i+)for(j=0;j3;j+)for(k=0;k4;k+)*(*(*(p+i)+j)+k)=i*100+j*10+k;/通过指针访问数组元素C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型【例5-8】动态创建多维数组分析:当用new动态创建多维数组时,如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,它是一个T类型数组的指针,而不是T类型指针,数组元素的个数为除最左边一维(最高维)外各维下标表达式的乘积。16171819202122232425262728for(i=0;i2;i+)for(j=0;j3;j+)for(k=0;k4;k+)/将指针cp作为数组名使用,通过数组名和下标访问数组元素coutpijk;coutendl;coutendl;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:0123012310111213101112132020212223212223100101102103100101102103110111112113110111112113120121122123120121122123F思考思考: :建立一个动态数组后,如果在程序的运行过程中,数组溢出,程序运行结果又将是什么?请读者尝试修改程序,使数组溢出并分析程序的运行结果。 5.3.6 5.3.6 指针与函数指针与函数 1 1、指针作为函数参数、指针作为函数参数 指针作为函数参数是一种地地址址传传递递方方式式。当需要在不同的函数之间传递大量数据时,程序执行时调用函数的开销就会比较大,这时,如果需要传递的数据是存放在一个连续的内存区域中,就可以采用指指针针作作为为函函数数参参数数,只传递数据的起始地址,而不必传递数据的值,这样就会减小开销,提高效率。 指针可以作为函数的形参,也可以作为函数的实参。如果以指针作为函数的形参,在调用时实参将值传递给形参,也就是使使实实参参和和形形参参指指针针变变量量指指向向同同一一内内存存地地址址,这样在函数运行过程中,通过形参指针对数据值的改变也同样影响着实参所指向的数据值,从而实实现现参参数数双双向向传传递递的的目目的的,即通过在被调用函数中直接处理主调函数中的数据而将函数的处理结果返回其调用者。【例【例5-95-9】用传指针方式实现两个数据交换 分分析析:用传值的方式无法实现两个数据交换。用指针作为形参,从实参传入要交换数据的地址,在函数体内将指针指向的两个数据交换存储位置,这样通过“釜釜底底抽抽薪薪”的方式实现了数据交换。为了实现不同类型的数据交换,形式参数采用void指针。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型1234567891011121314151617181920/*p5_9.cpp*实现两个数据交换的通用程序*/#includeusingnamespacestd;voidswap_i(int*num1,int*num2)/整型数交换intt;t=*num1;*num1=*num2;*num2=t;voidswap(void*num1,void*num2,intsize)/所有类型数据交换char*first=(char*)num1,*second=(char*)num2;for(intk=0;ksize;k+)chartemp;temp=firstk;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型指针作为函数形式参数指针作为函数形式参数 2122232425262728293031323334353637383940firstk=secondk;secondk=temp;int main()inta=3,b=6;doublex=2.3,y=4.5;charc18=John,c28=Antony;coutbeforeswap:a=ab=bendl;swap_i(&a,&b);coutafterswap:a=ab=bendl;coutbeforeswap:x=xy=yendl;swap(&x,&y,sizeof(x);coutafterswap:x=xy=yendl;coutbeforeswap:c1=c1c2=c2endl;swap(&c1,&c2,sizeof(c1);coutafterswap:c1=c1c2=c2endl;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:beforeswap:a=3b=6beforeswap:a=3b=6afterswap:a=6b=3afterswap:a=6b=3beforeswap:x=2.3y=4.5beforeswap:x=2.3y=4.5afterswap:x=4.5y=2.3afterswap:x=4.5y=2.3beforeswap:c1=Johnc2=Antonybeforeswap:c1=Johnc2=Antonyafterswap:c1=Antonyc2=Johnafterswap:c1=Antonyc2=John 5.3.6 5.3.6 指针与函数指针与函数 2 2 指针型函数指针型函数 除void类型的函数之外,每个被调用函数在调用结束之后都要有返回值,指指针针也也可可以以作作为为函函数数的的返返回回值值。当一个函数声明其返回值为指针类型时,这个函数就称为指针型函数。 指针型函数定义形式为: 其中,数据类型表明函数返回指针的类型;*表示函数的返回值是指针型,可以使用多个*返回多重指针。使用指针型函数的最最主主要要目目的的就是要在在函函数数调调用用结结束束时时把把大大量量的的数数据据从从被被调调用用函数返回到主调函数中函数返回到主调函数中,而通常非指针型函数调用结束后,只能返回一个值。在调用指针型函数时,需要一个同类型的指针变量接受返回的值。 数据类型数据类型 * * 函数名函数名( (参数表参数表););C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型12345678910111213141516/*p5_10.cpp*超长整数加法*/#includeusingnamespacestd;char *ladd(char *s1, char *s2) intn1,n2,n;char*res,c=0;n1=strlen(s1);/n1=数字串s1的长度n2=strlen(s2);/n2=数字串s2的长度n=n1n2?n1:n2;/数字串s1,s2最大长度res=newcharn+2;/申请存结果串的内存for(inti=n+1;i=0;i-)/将s1从低位开始搬到res,resi=in-n1?s1i-n-1+n1:0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.6 5.3.6 指针与函数指针与函数 171819202122232425262728293031323334for(i=n;i=0;i-)chartchar;tchar=in-n2?resi-0+s2i-n+n2-1-0+c:resi-0+c;/将数字符变成数c=tchar9 ? 1 : 0;/设进位resi=c0?tchar-10+0:tchar+0;/将数字变成数字字符returnres;int main()charnum1100,num2100,*num;cinnum1num2;num=ladd(num1,num2);coutnum1+num2=numendl;delete num;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:12345678901234 99999 12345678901234+99999=01234567900123312345678901234+99999=012345679001233 5.3.6 5.3.6 指针与函数指针与函数 5.3.6 5.3.6 指针与函数指针与函数 3 3 指向函数的指针指向函数的指针 在程序运行时,不仅数据要占用内存空间,程序的代码也被调入内存并占据一定的内存空间。每一个函数都有函数名,实际上,这个函函数数名名就就是是该该函数的代码在内存的起始地址函数的代码在内存的起始地址。 当调用一个函数时,编译系统就是根据函数名找到函数代码的首地址,从而执行这段代码。由此看来,函数的调用形式:函函数数名名(参参数数表表),其实质就是:函数代码首地址(参数表)函数代码首地址(参数表)。 函数指针:函数指针: 就是指向某个函数的指针,它是专专门门用用于于存存放放该该函函数数代代码码首首地地址址的的指指针针变变量量。一旦定义了某个函数指针,那么,它就与函数名有同样的作用,在程序中就可以象使用函数名一样,通过指向该函数的指针来调用该函数。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.6 5.3.6 指针与函数指针与函数 函数指针的定义语法形式如下:其中:数据类型为函数指针所指函数的返回值类型;形参表则列出了该指针所指函数的形参类型和个数。函数指针名与*外面的圆括号圆括号()()是必须是必须的,圆括号改变了默认的运算符的优先级,使得该指针变量被解释为指向函数的指针。如果去掉圆括号,将被解释为函数的返回值为指针。 数据类型数据类型 (* *函数指针名)(形参表);函数指针名)(形参表); C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.3.6 5.3.6 指针与函数指针与函数 函数指针在使用之前也要进行赋值使用之前也要进行赋值,使指针指向一个已经存在已经存在的函数代码的起始地址。语法形式为: 赋值符右边的函数名所指出的必须是一个已经声明过的,和函数指针具有相同返回类型和相同形参表的函数。在赋值之后,就可以通过函数指针名来直接引用该指针所指向的函数。即:该该函函数数指指针针可可以以与与函函数数名名一一样样,出出现现在在函函数数名名能能出出现现的任何地方。的任何地方。调用函数指针指向的函数有如下两种格式: 例如: intadd(inta,intb);/定义函数int(*fptr)(inta,intb);/定义函数指针fptr=add;/函数指针赋值,或fptr=&add;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型函数指针名函数指针名=函数名;函数名; 函数指针名函数指针名( (实参表实参表) ); (* (* 函数指针名函数指针名) () (实参表实参表) );5.3.6 5.3.6 指针与函数指针与函数 采用下列任何一种形式调用函数sum: add(1,2); /用函数名调用函数sum (*fptr)(1,2); /用指向函数的指针调用函数sum fptr(1,2); /用指向函数的指针调用函数sum【例【例5-105-10】用指向函数的指针实现各种算术运算的菜单程序。分分析析:为了实现菜单功能,需要定义一个函数指针数组来存储各函数名(地址),调用时通过各数组元素指向的函数名来调用对应的函数。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F说明说明: :虽然三种调用形式的结果完全相同,当用指向函数的指针调用函数add()时,习惯上使用(*fptr)(1,2),因为这种形式能更直观地说明是用指向函数的指针来调用函数。指向函数的指针常用来实现菜单程序,根据不同的选择执行菜单项中对应的功能,各功能由指向函数的指针实现。1234567891011121314151617181920/*p5_11.cpp*菜单程序*/#includeusingnamespacestd;int add(int a,int b) returna+b;int sub(int a,int b)returna-b;int mul(int a,int b)returna*b;int divi(int a,int b) if(b=0)return0x7fffffff;elsereturna/b;int (*menu )(int a,int b)=add,sub,mul,divi;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型2122232425262728293031323334int main() intnum1,num2,choice;coutSelectoperator:endl;cout1:addendl;cout2:subendl;cout3:multiplyendl;cout4:dividechoice;coutnum1num2;coutResult:menuchoice-1(num1,num2)endl;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:Select operator: 1:add 2:sub 3:multiply 4:divide3 Input number(a,b):4 5 Result:20F思考思考: :如果p5_11的运行结果中选择操作为:4,输入为:Inputnumber(a,b):50,输出结果将是什么?5.3.7 5.3.7 指针常量与常指针指针常量与常指针 1. 1. 指针常量指针常量 指针常量是相对于指针变量而言的,也就是指针值不能被修改的指针。 如果在定义指针变量时,指针变量前用const修饰,被定义的指针变量就变成了一个指针类型的常变量,指针类型的常变量简称为指针常量指针常量。 定义指针常量格式如下: 修饰符const与指针变量紧邻,说明指针变量不允许修改。既然指针变量的值不能修改,所以一定要在定义时给出初值。 数据类型数据类型* const * const 指针名指针名 = = 变量名;变量名; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型修饰符const与指针变量紧邻,说明指针的值不允许修改,所以一定要在定义时给出初值。inta=2;intb=3;int*constp=&a;/定义了一个指针常量并初始化p=&b;/错误,指针常量的值为常量,不能指向其它变量p=NULL;/错误,指针常量的值为常量,不能被修改5.3.7 5.3.7 指针常量与常指针指针常量与常指针 因为const修饰的是指针,而不是指针指向的对象的值,所以指针指向的对象的值可以被更改:*p=4;/错误,指针常量所指变量的值不可以被修改*p=b;/错误,指针常量所指变量的值不可以被修改 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型 2.2.常量指针常量指针如果在定义指针变量时,数据类型前用const修饰,被定义的指针变量就是指向常量的指针变量,指向常量的指针变量简称为常量指针。定义常量指针的格式如下: const const 数据类型数据类型* * 指针变量指针变量 = = 变量名;变量名;或 数据类型数据类型 const * const * 指针变量指针变量 = = 变量名;变量名;定义一个常量指针后,指针指向的对象的值不能被更改,即不能通过指针来更改所指向的对象的值,但指针本身可以改变,指向另外的对象。constinta=2;intb=3;constint*p=&a;/定义了一个常量指针并初始化p=&b;/正确,常量指针可以指向其它变量p=NULL;/正确,指针常量的值可以被修改5.3.7 5.3.7 指针常量与常量指针指针常量与常量指针 因为const修饰的是指针指向的值,而不是指针,所以指针指向的值不能被更改。*p=4;/正确,指针常量所指变量的值可以被修改*p=b;/正确,指针常量所指变量的值可以被修改为了防止通过一个非常量指针修改常量指针指向的值,将一个常量指针赋给一个非常量指针是错误的。int*q;q=p;/错误,将一个常指针赋给非常量指针可以将一个非常量指针赋给一个常量指针,这是因为const修饰的是指针指向的内容,而不是指针的值(地址值)。p=NULL;/正确p=q;/正确const用在数组的类型前修饰数组元素,数组元素为常量的数组的称为常量数组,常量数组的元素不可改变,也不可将地址赋值给非常量指针。constinta3=1,2,3;/定义常量数组a0=0;/错误,常量数组的元素不可修改int*p=a;/错误,常量数组的地址不能赋给非常量指针C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注意注意: :常数组的所有元素必须全部赋初值。常数组的所有元素必须全部赋初值。 const int a=1,2,3; /正确 const char a=1,2,3; /正确 const int a10=1,2,3; /错误,常数组元素没有全部赋初值 5.3.7 5.3.7 指针常量与常指针指针常量与常指针 3. 3. 指向常量的指针常量指向常量的指针常量 指针常量保护指针的值不被修改,常量指针保护指针指向的值不被修改,为了将两者同时保护,可以定义指向常量的指针常量,简称为常常指指针针常常量量。常常指指针针常常量量是是一个指向常量的指针,指针值本身也是一个常量。 常指针常量定义格式如下: 其中:左边的const与数据类型相结合,表明数据的值是常量;右边的const用在变量前,表明变量的值是常量。定义一个常指针常量后,修改指针的值与修改指针指向内容的值都是错误的: constinta=2;intb=3;int*q=&b;constint*constp=&a;/定义了一个常量指针并初始化p=&b;/错误,常指针常量的值为常量,不能指向其它变量p=NULL;/错误,常指针常量的值为常量,不能被改变*p=b;/错误,常指针常量所指的值为常量,不能被改变p=q;/错误,常指针常量的值为常量,不能被改变q=p;/错误,不能将一个常指针赋给非常指针 const const 数据类型数据类型* const * const 指针变量指针变量 = = 变量名;变量名;或 数据类型数据类型 const * const const * const 指针变量指针变量 = = 变量名;变量名; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注意注意: :常指针类型通常用作函数的形参,以防止在函数体内通过形参修改实参指向的值,以保护实参。 5.4 5.4 引用类型引用类型 引用:引用:从逻辑上理解,引用(reference)是已存在变量的别名(别名(alias),通过引用我们可以间接访问变量,指针也能间接访问变量,但引用在使用上相对指针更安全。引用的主要用途是为了描述函数的参数和返回值,特别是为了传递较大的数据变量。对引用型变量的操作实际上就是对被引用变量的操作。当定义一个引用型变量时,需要用已存在的变量对其初始化,于是引用就被绑定在那个变量上,对于引用的改动就是对它所绑定的变量的改动,反之亦然。定义一个引用型变量的语法格式为: 其中:数据类型应与被引用变量的类型相同;& &是引用运算符, 在这里是二元操作符;变量名为已定义的变量;例如: intx;int&refx=x;/refx是一个引用型变量,它被初始化为对整型变量x的引用数据类型数据类型 & & 引用变量名引用变量名 = = 变量名变量名; ; C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.4.1引用类型变量的说明及使用引用类型变量的说明及使用 当定义一个引用变量后,系统并并没没有有为为它它分分配配内内存存空空间间。refx与被引用变量x具具有有相相同同的的地地址址,即refx与x使用的是同同一一内内存存空空间间。对引用变量值的修改就是对被引用变量的修改,反之亦然。 例如: x=3;coutrefx;/结果为3refx=5;coutx;/结果为5引用变量的内存图如图5-6。从物理实现上看,引用是一个隐性的指针,即引用值是引用所指向的变量的值。引用与所引用的变量值的关系,看似直接访问,实为间接访问,这幕后的转换工作,是由编译做的。编译将引用转换为指针操作,因而,引用不能操作自身的地址,每次访问引用,实际上是在访问所指向的变量。与指针相比,引用不占用新的地址,节省内存开销,而且隐去了地址操作。引用封锁了对地址的可修改性,使得间接访问操作更安全了。指针是低级的直接操作内存地址的机制,其功能强大但使用不慎极易产生错误。在C+语言中,指针可由整型数强制类型转换得到,处理不当就可能对系统造成极大的破坏。另一方面,引用引用则封装了指针的特性,它不直接操作地址,不能由强制类型转换而得,因而具有较高的安全性,也不容易产生由于使用指针而常常产生呢的那些不易觉察的错误,因而,高级编程多用引用,低级编程多用指针,这主要是从安全因素着眼的。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.4.2引用与函数引用与函数 1. 1. 引用作为函数的参数引用作为函数的参数 当引用作为函数的形参,在进行函数调用时,进行实参与形参的结合,其结合过程相当于定义了一个形参对实参的引引用用。因此,在函数体内,对形参进行运算相当于对实参进行运算。与指针相比,引用作为函数参数具有两个优点优点: 函数体的实现比指针简单比指针简单。用指针作为形参,函数体内形参要带着*参加运算;而用引用作为形参,函数体内参加运算的为形参变量。 调用函数语法简单语法简单。用指针作为形参,实参需要取变量的地址;而用引用作为形参,与简单传值调用传值调用一样,实参为变量。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型123456789101112131415161718192021/*p5_12.cpp*用传引用的方式实现两个数交换*/#includeusingnamespacestd;void swap(int &refx,int &refy)inttemp;temp=refx;refx=refy;refy=temp;int main()intx=3,y=5;coutbeforeswap:x=xy=yendl;swap(x,y);coutafterswap:x=xy=yendl;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:beforeswap:x=3y=5afterswap:x=5y=35.4.2引用与函数引用与函数 2. 2. 引用作为函数的返回值引用作为函数的返回值 函数返回值类型为引用型,在函数调用时,若接受返回值的是一个引用变量,相当于定义了一个对返回变量的引用。若接受返回值的是一个非引用变量,函数返回变量的值赋给接受变量。 如果函数返回值类型为引用型,则要求返回值为左值。这样,函数调用式可以当作左值。12345678910111213/*p5_13.cpp*使用引用作为函数的返回值*/#includeusingnamespacestd;int max1(int a ,int n)/求数组a中元素的最大值intt=0;for(inti=0;iat)t=i;returnat+0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型1415161718192021222324252627int& max2(int a,int n)/求数组a中元素的最大值intt=0;for(inti=0;iat)t=i;returnat;int& sum(int a ,int n)/求数组a中元素的和ints=0;for(inti=0;in;i+)s+=ai;returns;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.4.2引用与函数引用与函数 28293031323334353637383940414243int main()inta10=1,2,3,4,5,6,7,8,9,10;intm1=max1(a,10);intm2=max2(a,10);int&m3=max2(a,10);int&m4=sum(a,10);coutm1=m1endl;coutm2=m2endl;coutm3=m3endl;coutm4=m4endl;m3+=10;max2(a,10)-=100;coutsum(a,10)endl;return0;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型运行结果运行结果运行结果运行结果:m1=10m2=10m3=10m4=-858993460-355.4.2引用与函数引用与函数 intint型变量接受函数返回型变量接受函数返回的的int &int &型值型值 通过引用变量修改返通过引用变量修改返回变量的回变量的 5.4.3常引用常引用常引用:常引用:如果在定义引用变量时用const修饰,被定义的引用就是常引用。 定义常引用格式如下: 定义一个常引用常引用后,就不能通过常引用更改引用的变量的值。 例如: inti(100);constint&r=i; 当试图使用r=200去更改i的值是错误的,但通过i本身可以改变i的值:例如: i=200; 此时r的值变成200。const const 数据类型数据类型& & 引用变量引用变量 = = 变量名;变量名;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.4.3常引用常引用 常常引引用用类类型型常常用用作作函函数数的的形形参参类类型型,把形参定义为常引用类型时,这样在函数体内就不能通过形参改变实参的值,保证了函数调用时实参是“安全”的。这样的形参称为只读形参只读形参。voidfun(constint&x,int&y)x=y;/错误,x不可修改y=x;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注意注意: :形参为常引用类型时,实参可以是常量、变量表达式;但如果为非常引用类型时,实参必须为左值实参必须为左值。对void fun(const int& x, int& y), 调用fun(100,200)是错误的, 调用fun(100,a)是正确的(a为变量)。5.5 5.5 结构与联合结构与联合 数组是由类类型型相相同同的数据元素构成的。然而,程序中往往需要处理一些由同类型数据元素所构成的数据。 例如,一个学生的基本情况由学号、姓名、性别、出生日期、成绩等数据元素构成,这些数据元素具有不同的数据类型,如果使用独立的不同数据类型的变量来描述这些信息,那么,变量之间的关系不能体现出来。C+也提供了描述不同数据类型的组合体的方法:结构和联合。结构和联合。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注注: :C+语言是在C语言的基础上改进和发展而来的,所以,有人将早期的C+语言中的 结 构 体 称 为 “带 函 数 的 结 构 体 ”, 即 我 们 即 将 要 学 习 的 C+中 的 “类(class)”。 5.5.1结构结构 结构类型结构类型: : 结结构构类类型型将不同数据类型组合成一个整体类型,是一种“用户自定义构造数据类型”。 定义结构类型的格式如下: 其中:struct 是关键字,表示定义的是一个结构类型;结构类型名必须是一个合法的标识符,结构类型名省略时表示定义的是一个无名的结构体;结构类型的成员数量不限,各成员构成成员表;数据类型可以是基本数据类型,也可以是构造数据类型;结构类型定义的结束符;不能省略。struct结构类型名数据类型1成员名1;数据类型2成员名2;数据类型n成员名n;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.5 5.5 结构与联合结构与联合 例如,下面定义了一个学生信息的结构类型: enumgenderman,ferman;struct studentlongno,birthday;/学号,生日charname22;/姓名gendersex;/性别floatscore;/成绩; 注注:结结构构体体及及结结构构体体变变量量的的具具体体用用法法,有有兴兴趣趣的的同同学学请请参参考考教教材材示示例例程程序序【例例5-135-13】,在在第第7 7章章 类与对象中我们将进一步对其进行深入学习。类与对象中我们将进一步对其进行深入学习。 C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注意注意: :结构类型是由多个成员类型组合而成,所以结构类型变量所占内存的大小理论上应为各个成员所占内存大小之和;为了提高对内存的存取速度,C+分配各个结构成员的内存空间以字为单位,以保证其地址在字的整数倍处,所以结构成员内存空间存在间隙。 定义了一个结构类型,但并没有定义变量,结构类型中的成员名既不能当作类型名也不能当作变量使用。 score=95; /错误,成员名不能当作变量 coutsizeof(name); /成员名不能当作类型名5.5.2联合联合 1.1.联合类型的定义联合类型的定义 联联合合类类型型是一种与结构类型类似的数据类型,它提供了一种可以将几种不同类型数据存放于同一段内存,对其中各个成员可以按名存取按名存取的机制。 联合类型定义的语法形式为: 与结构类型不同,联合类型虽然由多个成员类型组合而成,但联合类型变量的各个成员拥拥有有共共同同的的内内存存空空间间,联合类型变量所占内存的大小应为各个成员所占内存大小的最大者最大者。union 联合类型名 数据类型1 成员名1; 数据类型2 成员名2; 数据类型 n 成员名n;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.5.2 5.5.2 联合联合 在联合类型中,如果其中有构造数据类型,其大小为其中最长的基本数据类型的整数倍最长的基本数据类型的整数倍。 例如,下面定义了联合类型: unionUDatacharCh;shortSint;longLint;unsignedUint;floatf;doubled;charstr10;sizeof(UData)的理论值=sizeof(str)=10;sizeof(UData)的实际值=sizeof(double)*2=16;C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型5.5.2联合联合 联合变量在内存中的排列联合变量在内存中的排列 当定义联合变量后,联合变量在内存中获得了共同的内存,由于各个成员的数据类型不同,因此长度也不同。各成员在内存排列均从低地址开始,遵循“低地址低字节,高地址高字节”的原则。 例如: UData u;strcpy(u.str,“123456789); /给成员u.str赋初值 内存图如下: C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型F注注: : 联合类型及联合类型变量的具体用法,有兴趣的同学请参考教材示例程序【例【例5-145-14】。本章小结本章小结 枚举类型实质是一组整型符号常量,其中的每个常量都可进行各种运算,对 一个枚举变量赋值时一定要类型一致。 数组是一组同类型变量,可通过数组名加下标存取其中的单个变量。各个数 组元素在内存中顺序排列,数组名表示的是数组的起始地址。可以使用指针 运算符,用指针方式存取数组元素。 一个多维数组是以低维数组为元素的数组,多维数组在内存中的排列与一维 数组相同,即从低地址到高地址顺序排列。数组名、高维名表示的是数组的 地址。 数组名表示的地址不能是左值,但可以当作函数的形式参数,接受实参传送 的地址。 以0作为结尾符的字符数组为字符串,数组大小与字符串长度的关系为: sizeof(s) =strlen(s)+1; 地址变量称为指针,所有地址变量的长度都是4个字节。 地址变量存储数组的地址时(指针指向了数组),可通过指针名以指针方式 存取数组元素,也可将指针名当作数组名以数组方式存取元素。但指针比数 组多了一个存储地址的内存空间,因此指针名可以作为左值。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型本章小结本章小结 指针指向的动态申请的数组称为动态数组,动态数组所占的内存空间需要在 程序中进行释放。 指针可作为函数的形参,接受实参传送的地址。 引用是一个已存在变量的别名,它与被引用的对象共有内存单元,因此定义 一个引用型变量时一定要以一个已存在的变量作为初值。引用作为函数的 形参时,可用不赋初值,在函数体内引用变量代替实参进行运算,对形参 的改变反映到实参上。 引用型函数返回对象被一个引用型变量接受,引用型变量成为返回对象的别 名;若被一个非引用变量接收,则将返回变量的值赋给接受变量。引用型函 数还可以的是一个左值,接受右值对象的值。 常指针、常引用类型通常用作函数的形参,以防止在函数体内通过形参修改 实参指向的值,以保护实参。 结构类型是各种已存在与已定义类型的组合体,同类型结构变量之间赋值等 同于每一个成员之间的赋值,其中数组成员的赋值等同于数组的拷贝。 联合类型是各种已存在与已定义类型的共同体,联合变量各成员拥有共同的 内存空间。C+语语言言程程序序设设计计教教程程第第5章章构构造造数数据据类类型型
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号