第5章构造数据类型2.ppt

上传人:本田雅阁 文档编号:2257011 上传时间:2019-03-11 格式:PPT 页数:98 大小:561.01KB
返回 下载 相关 举报
第5章构造数据类型2.ppt_第1页
第1页 / 共98页
第5章构造数据类型2.ppt_第2页
第2页 / 共98页
第5章构造数据类型2.ppt_第3页
第3页 / 共98页
亲,该文档总共98页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《第5章构造数据类型2.ppt》由会员分享,可在线阅读,更多相关《第5章构造数据类型2.ppt(98页珍藏版)》请在三一文库上搜索。

1、C+语言程序设计教程 第11章 C+输入输出流,第5章 构造数据类型,主讲:尚明生 电子科技大学计算机学院 ,第5章 构造数据类型,1. 掌握枚举类型的使用; 2. 深入理解数组的概念, 掌握数组应用的一般方法; 3. 深入理解指针的概念,掌握指针的使用; 4. 注意指针与数组的区别,掌握多重指针以及指针与 数组的混合使用,合理应用动态数组; 5. 理解字符串的概念,能够灵活使用字符串; 6. 理解引用的概念,掌握引用型函数参数的用法; 7. 掌握结构与联合类型的使用,并注意二者的区别。,学习目标,C+语言程序设计教程 第5章 构造数据类型,5.1 枚举类型,1. 枚举类型的定义: “枚举”是

2、指将变量所有可能的取值一一列举出来,变量的取值只限于列举出来的常量。 枚举类型的声明的一般形式如下 : 枚举类型名以及枚举常量为标识符,遵循标识符的取名规则。 在定义一个枚举类型时,定义了多个常量,供枚举类型变量取值,称此常量为枚举常量。当没给各枚举常量指定值时,其值依次默认为0、1、2、;在定义枚举类型时,也可使用赋值另行指定枚举常量的值。,enum 枚举类型名 枚举常量1, 枚举常量2, 枚举常量n;,枚举!,C+语言程序设计教程 第5章 构造数据类型,5.1 枚举类型,枚举类型的定义: 例1: enum weekday SUN, MON, TUE, WED, THU, FRI, SAT

3、; 定义了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 枚举类型,枚举类型的定义说明: 枚举类型定义了以后就可以使用枚举常量、使用用枚举类型来定义变量,定

4、义枚举变量的方法与定义其它变量的方法一样。 例如: 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; 在定义变量时,可以顺便给出初值,若不给初值,默

5、认初值为随机的无意义的数。,C+语言程序设计教程 第5章 构造数据类型,5.1 枚举类型,枚举类型的使用: 用枚举类型建立枚举变量后就可以对枚举变量实施赋值以及进行其它运算了,对枚举变量进行赋值,其值要求为同一枚举类型。否则,在编译时出错。 例如: weekday d1,d2,d3,d4; d1=SUN; d2=6; /错误 d3=Shanghai; /错误 其中对d2所赋之值是整数6,不是枚举常量;可以采用将一个整型值强制转换成同类型的枚举常量赋给枚举变量。 枚举常量、枚举类型的变量可进行算术运算、关系运算。 对枚举类型实施算术、关系运算时,枚举值转换成整型值参加运算,结果为整型值。所以,如

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章 函数,注意: 枚举常量是常量,不是变量,所以不能对枚举常量进行

7、赋值。 例如: 在上例中不能进行赋值 Shanghai=Beijing; 枚举常量的值不是列举的字符串,其值为整数。 编译器对赋给枚举变量的对象(数)进行类型检查,如类型不相符则发出警告。 当类型相 同,而值超出此类枚举类型枚举常量范围时,也是正常的。,枚举类型定义,C+语言程序设计教程 第5章 构造数据类型,【例5-1】输入城市代号,输出城市名称。,5.1 枚举类型,运行结果: Input a city number (-1 to exit): 1 Shanghai 8 Invalid city number! -1,C+语言程序设计教程 第5章 构造数据类型,枚举类型的使用,5.1 枚举类

8、型,5.2 数组,数组: 数组是一组在内存中依次连续存放的、具有同一类型的数据变量所组成的集合体。其中的每个变量称为数组元素,它们属于同一种数据类型,数组元素用数组名与带方括号的数组下标一起标识。数组可以是一维的,也可以是多维的。 特点: 若干个同类型的数据元素,并且各个数据元素之间存在某种次序关系。这类数据有一个共同的特点:它们有若干个同类型的数据元素,并且各个数据元素之间存在某种次序关系。,C+语言程序设计教程 第5章 构造数据类型,5.2.1 一维数组定义与使用,一维数组定义的一般形式为: 说明: 数组元素的类型可以是void型以外的任何一种基本数据类型,也可以是已经定义过的构造数据类型

9、; 数组名是用户自定义的标识符,用来表示数组的名称,代表数组元素在内存中的起始地址,是一个地址常量。 常量表达式必须是unsigned int类型的正整数。表示数组的大小或长度,也就是数组所包含数据元素的个数。 是数组下标运算符,在数组定义时用来限定数组元素的个数。,数据类型 数组名常量表达式;,C+语言程序设计教程 第5章 构造数据类型,注意: 数组属于构造数据类型,在使用之前必须先进行类型定义。,5.2.1 一维数组定义与使用,数组元素的类型可以是void型以外的任何一种基本数据类型,也可以是已经定义过的构造数据类型; 例如:下面定义了2个不同类型的数组: int a5; /定义了一个5个

10、元素的整型数组a weekday b10; /定义了一个10个元素的枚举数组b,weekday 为已定义的枚举型。 数据类型相同的多个数组可以在同一条语句中予以定义。 例如: int a110, a220; /同时定义了两个整型数组 数据类型相同的的简单变量和数组也可以在一个语句中定义。例如: int x, a20; /同时定义了一个整型变量和一个整型数组,C+语言程序设计教程 第5章 构造数据类型,5.2.1 一维数组定义与使用,数组定义之后,系统会将从内存中为其分配一块连续的存储空间,从第1个数据元素开始依次存放各个数组元素。例如,定义的数组a其内存排列(分配)示意图如图5-1所示。 例如

11、: int a5; /定义了一个5个元素的整型数组a,C+语言程序设计教程 第5章 构造数据类型,5.2.1 一维数组定义与使用,一维数组初始化: 是指在定义数组的同时给数组中的元素赋值。 其一般语法形式为: 初值1,初值2, 初值n称为初值表,初值之间用逗号,分隔, 所有初值用 括起来。 初值可以是一个变量表达式,初值与数组元素的对应关系是:初值i给数组第i个元素;所以,初值个数n不能超过数组的大小。 若初值表中初值个数(项数)小于数组的大小,则未指定值的数组元素被赋值为0;但初值表中项数不能为0。例如: weekday b10=MON,WED,FRI; 当对全部数组元素赋初值时,可以省略数

12、组的大小,此时数组的实际大小就是初值列表中初值的个数。例如: char str = a, b, c, d, e ; /数组str的实际大小为5。 在函数中定义数组时,如果没有给出初值表,数组不被初始化,其数组元素的值为随机值;在函数外定义数组如果没有初始化,其数组元素的值为0。 数组初值表的可以用一个逗号结尾,其效果与没有逗号一样。,数据类型 数组名 常量表达式 =初值1, 初值2, 初值n;,C+语言程序设计教程 第5章 构造数据类型,5.2.1 一维数组定义与使用,对一维数组实施的存取操作有两类:存取数组元素与读取数组元素的地址。数组元素是通过数组名及下标来标识的,这种带下标的数组元素也称

13、为下标变量,下标变量可以象简单变量一样参与各种运算。 存取一维数组元素的一般语法形式为: 说明: 下标表达式可以是变量表达式,用来标识数组元素;不同于数组定义时用来确定数组长度的常量表达式。 当定义了一个长度为n的一维数组a,C+规定数组的下标从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-2】学生成绩排序。 分析:学生成绩由键盘输入,当输入一个负数

14、时,输入完毕。 采用直观的“选择排序法”进行排序,基本步骤如下: 将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章 构造数据类型,数组定义,数组使用,C+语言程序设计教程 第5章 构造数据类型,运行结果: 80 90 95 70 -1 95 90 80 70,C+语言程序设计教程 第5章 构造数据类型,5.2.1 一维数组定义与使用,4. 数组的地址 数组

15、元素的地址通过数组名来读取,其格式如下: 由于其地址不是实际的地址值,称这个地址表达式为符号地址表达式。例如: 一维数组元素a5的符号地址表达式为a+5。 若a是一个int型数组,数组的符号地址表达式a+n所表达的地址是第n+1个元素an的地址,代表的实际地址值为: a+n*sizeof(int) 而不是:a+n。,C+语言程序设计教程 第5章 构造数据类型,数组名+整型表达式;,5.2.1 一维数组定义与使用,C+语言程序设计教程 第5章 构造数据类型,使用数组要注意: 在使用数组时最常犯的错误是数组元素越界,包括上标越界和下标越界。上标越界是指数组元素的访问地址值超过了数组的起始地址;下标

16、越界是指数组元素的访问地址越过了数组中最后一个数组元素的地址。对于这种错误,编译器无法知道,往往在运行时出错。因此在程序设计时应格外注意。 数组名是一个地址常量,不能作为左值(赋值的目标)。因此,不能将一个数组 整体拷贝给另外一个数组。 例如: int a5,c5,i; a=c; /错误! 正确的方法是将对应的元素进行拷贝,见下列程序段: for(i=0;i5;i+) ai=ci; /将数组c中元素的值拷贝到数组c的对应元素中 在函数中,可以将一个一维数组作为函数的形式参数,用来接受一个一维数组传递过来的地址。,5.2.2 二维数组的定义与使用,二维数组的定义的一般形式为: 其中: 常量表达式

17、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 二维数组的定义与使用,如果一维数组描述排列成一行的数据,那么,二维数组则描述若干行

18、这样的数据。因此,二维数组可以看作是数学上的一个矩阵。第1维元素个数为矩阵的列数,第2维元素个数为矩阵的行数。 二维数组的定义格式可以写成: 定义一个二维数组后,系统为它分配一块连续的内存空间。 二维数组amn占内存空间的计算公式为:,数据类型 数组名行数列数;,C+语言程序设计教程 第5章 构造数据类型,sizeof(数组名);或 m*sizeof(a0); 或 m*n*sizeof(数据类型),5.2.2 二维数组的定义与使用,既然一个二维数组是由若干个一维数组排列构成,二维数组在内存中的排列顺序为:先顺序排列每个一维元素,构成一维数组;再将各个一维数组顺序排列,构成二维数组。 int M

19、23的排列顺序为:先将3个int元素排列组成2个一维数组M0, M1。 M0:M00,M01,M02 M1:M10,M11,M12 再将2个一维数组排成一个二维数组。 M: M0, M1 数组M在内存中的排列图如图所示。,C+语言程序设计教程 第5章 构造数据类型,5.2.2 二维数组的定义与使用,二维数组的初始化 : 其中初值表具有两种形式:嵌套的初值表,线性初值表。 (1) 嵌套初值表 以二维数组Mmn为例,嵌套初值表的格式为: 嵌套初值表由一维初值表嵌套构成,各层构成规则与一维数组的初值表相同。 例如: int M34=1,2,3,4,3,4,5,6,5,6,7,8; /M数组元素被全部

20、初始化 int a23=1,0,0,1; /初始化了部分数组元素 int b3=1,2,3,; /初始化了全部数组元素 int d3=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)线形初值表 线形初值表与一维数组的初值表相同,初值表的项数不超过各维元素个数的乘积(总元素个数)。 数组元素按内存排列顺序依次从

21、初值表中取值,下列各数组使用了线形初值表,结果与使用嵌套初值表相同。 例如: int M34=1,2,3,4,3,4,5,6,5,6,7,8; /M数组元素被全部初始化 int a23=1,0,0,0,1,1; /初始化了全部数组元素, 一部分元素未给初值 int b 3=1,0,0,0,0,0; /初始化了全部数组元素, 省略了高维元素个数 当使用线形初值表而省略高维元素个数时,高维元素个数为: 例如: int b 3=1,0,0,0;/高维元素个数为2,C+语言程序设计教程 第5章 构造数据类型,向上取整数(线形初值表项数/低维元素个数),5.2.2 二维数组的定义与使用,(3)二维数组的

22、存取 存取维数组元素的格式为: 说明: 行下标表达式与列下标表达式的值同样从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

23、+j)*sizeof(数据类型),二维数组定义 并初始化,二维数组使用,C+语言程序设计教程 第5章 构造数据类型,运行结果: 70 71 72 73 74 82 83 84 85 86 92 93 94 95 96 -1 0 0 0 0 70 71 72 73 74 360 82 83 84 85 86 420 92 93 94 95 96 470 - 81.3333 82.3333 83.3333 84.3333 85.3333 416.667,C+语言程序设计教程 第5章 构造数据类型,5.2.3 多维数组,(1)三维以及高于三维的数组称为多维数组 多维数组的定义与二维数组类似,可以一次

24、定义,也可以逐步由低维数组定义。 例如: int b234; /定义了一个三维数组 也可用下列方式步定义: typedef int B134; B1 b2; 多维数组在内存的排列方式同样是先排低维数组,由低向高依次排列。 如:b234的排列顺序为: b00:b000,b001,b002,b003 b0 b01:b010,b011,b012,b013 b b02:b020,b021,b022,b023 b10:b100,b101,b102,b103 b1 b11:b110,b111,b112,b113 b12:b120,b121,b122,b123,C+语言程序设计教程 第5章 构造数据类型,5

25、.2.3 多维数组,(2)多维数组的初始化与存取 多维数组的初始化形式与二维数组类似:有嵌套初值表、线性初值表两种形式。使用线性初值表初始化时,数组元素按内存排列顺序依次从初值表中取值。 对多维数组进行存取包括对数组元素的存取和对数组元素的地址的读取,当一个多维数组的下标数与维数相同时,为对数组元素的存取。 当下标个数小于维数时表示的是一个地址,表示地址时,下标也不能越界。 如:下列都是b234的地址表达式。 b1; /b100的地址; b2; /错误,下标越界; b0+1; /与b01相同,b010的地址。 b12; /b120的地址 b12+4; /b124的地址,但数组b中没有b124这

26、个元素, 故指向了其它地方。,C+语言程序设计教程 第5章 构造数据类型,C+语言程序设计教程 第5章 构造数据类型,运行结果: Add of b: &b=0012FEF0 b=0012FEF0 &b000=0012FEF0 Add of bk: &bk=0012FF40 bk=0012FF40 b+k =0012FF40 &b0+k=0012FF40 &bk00=0012FF40 Add of bkm: &bkm=0012FF5E bkm=0012FF5E bk+m =0012FF5E &b00+k*M+m=0012FF5E &bkm0=0012FF5E &b00+(k*sizeof(b0)

27、/sizeof(b00)+m=0012FF5E Add of bkmn: &bkmn=0012FF66 bkm+n=0012FF66 &b000+k*M*N+m*N+n=0012FF66 &b000+(sizeof(b0)*k+sizeof(b00)*m)/sizeof(b000)+n=0012FF66,C+语言程序设计教程 第5章 构造数据类型,5.2.4 数组与函数,数组名是一个地址,不能当作一个左值,但是可以作为函数的形参,接受实参传送来的地址。当形参接受实参传送来的地址后,形参数组与实参共享内存中的一块空间。函数体通过形参对数组内容的改变会直接作用到实参上。 数组名作为形参是数组应用的

28、一个重要方面。 注意: (1)使用数组名传递地址时,虽然传递是地址,但形参与实参的地址 (数组)类型应一致。 (2)形式参数中数组元素个数没有给定,因此,在函数体中,对数组存取的下标可以为任意值而不会出现编译错误。但是,当这个下标超过了实参数组的元素个数范围时,存取的就不是实参数组中的内容了。,C+语言程序设计教程 第5章 构造数据类型,C+语言程序设计教程 第5章 构造数据类型,数组作为函数形式参数,运行结果: 20060101 1 82 86 168 20060102 1 75 86 161 20060204 2 86 90 176 20060205 2 90 83 173 2006020

29、3 2 80 80 160,C+语言程序设计教程 第5章 构造数据类型,数组作为函数形式参数,5.2.5 字符数组与字符串,存放字符型数据的数组称为字符数组。字符数组也分为一维数组和多维数组。 前述的数组的定义及初始化同样适用于字符数组,除此以外,C+对字符数组的初始化还可以使用字符串形式。 1.用字符进行初始化 例如: char s1 =C,h,i,n,a; char s2 4=H,o,w,a,r,e,y,o,u; 2.用字符串进行初始化 例如: char s3 =“China“; char s4 4=“how“, “are“, “you“;,C+语言程序设计教程 第5章 构造数据类型,3.

30、 字符数组的使用 字符数组也是数组,我们同样可以通过数组名及下标引用数组中的元素。 为方便对字符与字符串的处理,C+提供了许多专门处理字符与字符串的函数,这些函数原型在各自的头文件中定义。 下表列出了常用的字符与字符串处理函数的调用方法与功能简介,函数原形与详细的功能可以从C+编译器的帮助文档中获得。,C+语言程序设计教程 第5章 构造数据类型,5.2.5 字符数组与字符串,常用字符与字符串处理函数,C+语言程序设计教程 第5章 构造数据类型,5.2.5 字符数组与字符串,常用字符与字符串处理函数,C+语言程序设计教程 第5章 构造数据类型,1 ChenHailing 2 CuiPeng 3

31、GongJing 4 HuangPin 5 LianXiaolei 6 LiuNa 7 LiuPing 8 ZhouZijun Input the searching name:LiuPing Position:7,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,指针是C+语言最重要特性之一,也是C+的主要难点。 指针提供了一种较为直观的地址操作的手段,正确地使用指针,可以方便、灵活而有效地组织和表示复杂的数据。 指针在C+程序中扮演着非常重要的角色,从某种程度上而言,如果不能深刻的理解指针的概念,正确而有效的掌握指针,就不可能真正学好C+,但是指针也是我们最容易产生困惑并导致程序出

32、错的原因之一。,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,1. 地址与指针 地址: 当定义一个变量后,内存中将会划出一块由若干个存储单元组成的区域,用于保存该变量的数据。在内存里每个存储单元都有各自的编号,称为地址。 指针: 在C+中,提供了指针类型,它是一种用于存放内存单元地址的变量类型,地址就存储在这种指针类型的变量中。正因为指针变量存储的是地址,用它来指明内存单元,所以形象地称这种地址变量为指针。,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,2. 指针变量的定义 每存储一个地址,就要定义一个指针变量。定义指针变量的格式如下: 数据类型是指针变量所指向对象的数

33、据类型,它可以是基本数据类型,也可以是构造数据类型以及void 类型。 变量名是用户自定义的标识符。 *表示声明的变量是一个指针变量,而不是普通变量。 例如: int *ip; /定义了一个int型的指针变量ip float *fp; /定义了一个float型指针变量fp typedef int A10; A *ap; / 定义了一个A类型的指针变量ap sizeof(ip)=sizeof(fp)=sizeof(ap)=4;,数据类型 * 变量名;,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,3指针的初始化与赋值 定义了一个指针,只是得到了一个用于存储地址的指针变量。若指针变量既

34、没有初始化,也没有赋值,其地址值是一个随机的数。 (1)不要将一个非地址常量、变量以及无意义的实际地址赋给指针变量。如: int *p=100; /错误,100是一个int型常量,不是一个地址常量。 int *p=(char *)100; /危险!100是一个无意义的实际地址, 可能指向危险区域。 (2)可以使用一个已初始化的指针去给另一个指针赋值,但类型必须一致如果不一致,可 进行强制类型转换。 char *p=NULL; int *ip=(int *)p+100; /将char型指针强制转化成int型指针。 (3)对于基本数据类型的变量、数组元素我们可以使用取地址运算符 /定义void类型

35、的指针,数据类型 *指针变量名=初始地址表达式;,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,4指针运算 指针变量存放的是地址,因此指针的运算实际上就是地址的运算,但正是由于指针的这一特殊性,使指针所能进行的运算受到了一定的限制。指针通常进行下列几种运算:赋值运算、取值运算、算术运算、相减运算、比较运算。 (1)* 和,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,(2)指针与整数的加减运算 指针的加减运算与普通变量的加减运算不同,由于指针存储的是变量的内存地址,指针加上或减去一个整数n,表示指针从当前位置向后或向前移动n个sizeof(数据类型)长度的存储单元。因此

36、对于不同的数据类型,n的实际大小就不同。 例如程序段: int b234; typedef char A10; 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, 0013FF80 0013FF84, 0013FF84, 0

37、013FF84, 0013FF88, 0013FF8A,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,(3)指针自增、自减运算 指针的自增、自减运算是指针加减运算的特例。指针的自增或自减表示指针从当前位置向后或向前移动sizeof(数据类型)长度的存储单元。 例如:程序段: int *p, *q, a=5; p= /这是一种常用的表达式,依次执行:*q=*p, q+, p+ (4)两指针相减 当两个指针指向同一数组时,两个指针的相减才有意义。两个指针相减的结果为一整数,表示两个指针之间数组元素的个数。,C+语言程序设计教程 第5章 构造数据类型,5.3 指针,(5)两个指针的比较运

38、算 两个指针的比较一般用于下列两种情况:一是比较两个指针所指向的对象在内存中的位置关系;二是判断指针是否为空指针。 5 void类型指针 指向void类型的指针是一种不确定类型的指针,它可以指向任何类型的变量。实际使用void型指针时,只有通过强制类型转换才能使void型指针得到具体变量的值。在没有转换前void型指针不能进行指针的算术运算。 例如: void *vp; /定义了一个void型指针vp int i=6, *ip; vp=,C+语言程序设计教程 第5章 构造数据类型,5.3.2 指针与字符串,字符型指针: 用于存放字符型变量的地址,而字符串的本质是以0结尾的字符数组,一个字符型指

39、针存储了字符数组的第一个元素的地址,也就存储了字符串的地址,这个指针就指向了字符串。 在定义一个字符数组时,可以将一个字符串常量作为初值,但将字符串常量作为初值赋给字符数组和将字符串常量作为初值赋给字符指针变量,二者的含义是不同的。 例如: char str5=“abcd“; char *p_str=“abcd“; 在上述字符串定义有下列不同: (1) 字符数组str5被赋值为“abcd”,因此,数组str的五个数组元素的值分别为 字符a、b、c、d和0。字符指针p_str被赋值为“abcd”,则意味着 指针p_str的值为字符串常量“abcd“的第一个字符a在内存中的地址。 (2) 字符指针

40、p_str比str多分配了一个存储地址的空间,用于存储字符串的首地 址。,C+语言程序设计教程 第5章 构造数据类型,5.3.3 指针与数组,1.使用指针操作符*存取数组 指针的加减运算的特点使得指针操作符特别适合处理存储在一段连续内存空间中的同类型数据。这样,使用指针操作符来对数组及其元素进行操作就非常方便。 (1) 一维数组的指针操作 当定义数组一维数组T aN (T为类型),下式为存取数组元素ai的等效方式: *(a+i); 而a+i为ai的地址。 (2) 多维数组的指针操作 对于多维数组,使用指针同样可以灵活访问数组元素。若定义数组 T bKMN, 下式为存取数组元素aijk的等效方式

41、: 例如: *(*(*(b+i)+j)+k); 其中:*(*(b+i)+j)+k为bijk的地址,即 *(b+i)为bi00的地址,即bi;,C+语言程序设计教程 第5章 构造数据类型,5.3.3 指针与数组,2.指针数组 指针数组是以指针变量为元素的数组,指针数组的每个元素都是同一类型的指针变量。 在指针数组的定义中有两个运算符:*和 ,运算符 的优先级高于*,所以*pN等价于*( pN),p N表示一个数组,而*表示数组元素为指针变量。 例如: int *p_a5; 定义了一个指针数组,其中有5个数组元素,每个数组元素都是一个int类型的指针。,注意: 对指针数组的存取同样可以使用指针方式

42、、数组方式、以及指针与数组结合的方式。一维指针数组与二维指针数组对应,可采用存取二维数组的方式存取。 指针数组的每一个元素都是一个指针,因此必须先赋值,后引用。,C+语言程序设计教程 第5章 构造数据类型,5.3.3 指针与数组,3)数组指针 数组指针是指向数组的指针。 虽然运算符 的优先级高于*,但是,在数组指针的定义式中,(* 指针名)改变了这种优先级,它表明定义的首先是一个指针,然后才是什么类型的指针。 例如: int (* a_p) 5; 等效于下列定义方式: typedef int I_A5; I_A *a_p;,C+语言程序设计教程 第5章 构造数据类型,5.3.4 多重指针,如果

43、已经定义了一个指针类型,我们再定义一个指针,用于指向已经定义的指针变量,后面定义的指针变量就是一个指向指针的指针变量,简称指向指针的指针,这样的指针也称二重(级)指针。 三重及以上的指针统称为多重指针。 例如: int *pp; 定义了一个二级指针变量,等效于下列定义方式: typedef int * P; P *p; 二级指针常用来指向一个指针数组。 例: int a23=1,2,3,4,5,6; /声明并初始化二维数组 int *p_a3; /声明整型指针数组 p_a0=a0; /初始化指针数组元素 p_a1=a1; int *pp; pp=p_a;,C+语言程序设计教程 第5章 构造数据

44、类型,5.3.4 多重指针,注意:在使用二级指针时经常容易犯两类错误。 (1)类型不匹配 例如: pp=a; /错误,因为pp是一个int*型变量,a是一个int23型的地址 pp=只是定义了一个指针变量,变量中的内容(地址)是一个无意义的地址,而*p2=&i是对无意义的内存单元赋值,这样是错误与危险的。正确的作法是从第一级指针开始,逐级初始化。,C+语言程序设计教程 第5章 构造数据类型,5.3.4 多重指针,3)逐级初始化多级指针 例: int i=3; int *p2; int *p1; p1= /结果为5 上述两个二级指针在内存中 的分布如右图所示。,C+语言程序设计教程 第5章 构造数据类型,5.3.4 多重指针,当一个二级指针指向一个指针数组后,对数组元素的存取可以使用指针方式、数组方式、混合方式: 例如: pij; /存取数组元素aij的数组方式; *(*(p+i)+j); /存取数组元素aij的指针方式; *(pi+j); /存取数组元素aij的混合方式; 一般而言,二重指针就足够使用了,三重指针使用场合就很少了,使用多重指针同样要:,注意: 不管是多少重指针,定义后,只建立了一个指针变量,分配一个指针变量的空间。 要初始化多重指针,要从第一层开始,逐步向高层进行。,C+语言程序设计教程 第5章 构造数据类型,5.3.5 动态内存分配,在C+中,动态内存

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1