《C语言程序设计课件第章》由会员分享,可在线阅读,更多相关《C语言程序设计课件第章(30页珍藏版)》请在金锄头文库上搜索。
1、C C语言程序设计课件第章语言程序设计课件第章第十章第十章二维数组二维数组和指针和指针2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2 22009.8 2009.8 朱立华朱立华 俞琼俞琼 王立柱王立柱3 3内容提要内容提要与二维数组相关的各类指针与二维数组相关的各类指针 二维数组的初始化及元素访问方式二维数组的初始化及元素访问方式二维数组的定义二维数组的定义, ,其中涉及的其中涉及的3 3种类型种类型本章介绍二维数组的有关知识本章介绍二维数组的有关知识动态二维数组空间的申请与释放动态二维数组空间的申请与释放( (选讲选讲) )内容提要内容提要
2、二级指针二级指针列指针列指针行指针行指针一维指针数组一维指针数组利用二级指针申请动态二维数组空间利用二级指针申请动态二维数组空间如何依次释放申请的所有动态空间如何依次释放申请的所有动态空间2009.8 2009.8 朱立华朱立华 俞琼俞琼 王立柱王立柱4 4重点难点提示重点难点提示重点难点提示重点难点提示二维数组的定义与使用二维数组的定义与使用二维数组与行指针二维数组与行指针二维数组与列指针二维数组与列指针动态演动态演示示动态演动态演示示二维数组与指针数组二维数组与指针数组动态演动态演示示动态演动态演示示二维数组的定义n哪里需要二维数组?哪里需要二维数组?类型相同的一组数类型相同的一组数, ,
3、如果在序列中如果在序列中只受一种序号标明只受一种序号标明其在整其在整个序列中的顺序个序列中的顺序, ,用用一维数组一维数组, ,例如例如: :1 1门课各个同学的成绩门课各个同学的成绩 类型相同的一组数类型相同的一组数, ,如果在序列中需要用如果在序列中需要用两种序号标明两种序号标明其在其在整个序列中的顺序整个序列中的顺序, ,则要用则要用二维数组二维数组, ,例如例如: :3 3门课各个同学的门课各个同学的成绩成绩矩阵问题强调元素所在的行、列位置矩阵问题强调元素所在的行、列位置, ,必须用必须用二维数组二维数组n二维数组的定义形式:二维数组的定义形式:类型标识符类型标识符 数组名数组名 整型
4、常量表达式整型常量表达式1 1 整型常量表达式整型常量表达式22;例:例:int a43int a43;/定义定义4 4行行3 3列的整型二维数组,数组名为列的整型二维数组,数组名为a a 二维数组的二维数组的元素类型元素类型二维数组名是一个用二维数组名是一个用户自定义标识符户自定义标识符指明二维数指明二维数组的行数组的行数指明二维数指明二维数组的列数组的列数2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱5 5二维数组的定义n二维数组的实质分析:二维数组的实质分析:二维数组是二维数组是一维数组的一维数组(递归定义)一维数组的一维数组(递归定义)
5、例:例:int a43;int a43;(1)(1)这里,这里,a a是二维数组名是二维数组名,也可以理解成是,也可以理解成是一维数组名一维数组名a a,它有它有4 4个元素,分别为个元素,分别为a0a0、a1a1、a2a2、a3a3(2)a(2)a的的4 4个元素不是普通的变量,而是都分别是一维数组,个元素不是普通的变量,而是都分别是一维数组,称为称为行一维数组行一维数组,每一个都有,每一个都有3 3个个intint型元素型元素,例:,例:a0a0的的3 3个元素为个元素为:a00:a00、a01a01、a02a02(3)(3)因此,二维数组因此,二维数组a a中共有中共有1212(4*34
6、*3)个个intint型的元素:型的元素:a00a00、a01a01、a02a02a10a10、a11a11、a12a12a20a20、a21a21、a22a22a30a30、a31a31、a32a32它们它们4个称为个称为行一维数组行一维数组第第1个下标个下标称为行下标称为行下标第第2个下标个下标称为列下标称为列下标这这1212个元素称为个元素称为二维数组元素二维数组元素行数行数列数列数2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱6 6二维数组的定义n二维数组定义中含有二维数组定义中含有3 3种类型种类型: :例:例:int a43;int
7、 a43;(1 1)int 43int 43:是二维数组:是二维数组a a的类型标识的类型标识(2 2)int 3:int 3: 是行一维数组是行一维数组a0a3a0a3的类型标识,也是的类型标识,也是二维数组的基类型二维数组的基类型(3 3)int:int:是二维数组元素是二维数组元素a00a32a00a32的类型,也是行的类型,也是行一维数组的基类型一维数组的基类型n二维数组定义中的二维数组定义中的常量与变量常量与变量: :例:例:int a43;int a43;(1 1)二维数组)二维数组a a和行一维数组和行一维数组a0a3a0a3均为均为指针常量指针常量(2 2)二维数组元素)二维数
8、组元素a00a32a00a32是是intint型的型的变量变量2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱7 7二维数组的初始化n二维数组在定义的同时可为其元素赋值,称为初始化,二维数组在定义的同时可为其元素赋值,称为初始化,原则:行从左到右依次,每行中列从左到右依次原则:行从左到右依次,每行中列从左到右依次(1 1)逐行初始化逐行初始化: int a43=1,2,3,4,5,6,7,8,9,10,11,12; (2 2)行数可以缺省,列数不能省,自动算行行数可以缺省,列数不能省,自动算行 : : int a 3=1,2,3,4,5,6,7,
9、8,9,10,11,12; (3 3)不分行,用类似一维数组的方式初始化不分行,用类似一维数组的方式初始化: :int a43=1,2,3,4,5,6,7,8,9,10,11,12; (4 4)初始化数据不足,系统用初始化数据不足,系统用0 0补充:补充: int a43=1,2,4,5,7,8,9,10,11,12; (5 5)最简单的初始化最简单的初始化: int a43=0; 每行单独用一每行单独用一对大括号括起对大括号括起共有两层大括号共有两层大括号只有一层大括号只有一层大括号等效于等效于int a43=1,2,0,4,5,0,7,8,9,10,11,12;第第1个元素初始化为个元素初
10、始化为0,其余未,其余未初始化的元素值自动为初始化的元素值自动为0行数计算出来为行数计算出来为4,不初始化时不能缺少行数,不初始化时不能缺少行数2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱8 8二维数组的初始化n错误的初始化示例错误的初始化示例: :(1 1)未遵守行从左至右依次初始化原则未遵守行从左至右依次初始化原则: int a43= ,4,5,6,7,8,9,10,11,12; (2 2)同一行中未遵守列从左至右依次初始化原则同一行中未遵守列从左至右依次初始化原则: : int a43=1, ,3,4,5,6,7,8,9,10,11,1
11、2; int a43=1,2,3,5,6,7,8,9,10,11,12; (3 3)不分行,用类似一维数组的方式初始化,未按顺序不分行,用类似一维数组的方式初始化,未按顺序: :int a43=1,2, ,4, ,6,7,8,9,10,11,12 ;(4 4)省略列号省略列号: :int a4 =1,2,3,4,5,6,7,8,9,10,11,12;中间缺少两个元素,不符合中间缺少两个元素,不符合从左到右依次的原则从左到右依次的原则第第1 1行没有初始化,后行没有初始化,后面行就不能初始化面行就不能初始化第第1 1行第行第2 2列没有初始化,列没有初始化,第第3 3列就不能初始化列就不能初始化
12、第第2 2行第行第1 1列没有初始化,第列没有初始化,第2 2、3 3列就不能初始化列就不能初始化二维数组初始化中列二维数组初始化中列号一定不能省略号一定不能省略2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱9 9二维数组元素的访问a00a00 a01a01 a02a02 a10a10 a11a11 a12a12 a20a20 a21a21 a22a22 a30a30 a31a31 a320i 30 j 2a0a1a2a3n二维数组元素可随机访问,因为每个元素地址可计算二维数组元素可随机访问,因为每个元素地址可计算Loc(aij)=a+(i*m
13、+j)*sizeof(Loc(aij)=a+(i*m+j)*sizeof(二维数组元素类型)二维数组元素类型)n数组元素的表示形式:数组元素的表示形式:例:例:int a43;int a43;(1 1)最常用的是下标(行、列)法)最常用的是下标(行、列)法:aijaij(2 2)间接引用法与下标法结合)间接引用法与下标法结合: : *(ai+j)*(ai+j)、 (*(a+i)*(a+i))jj(3 3)间接引用法)间接引用法: : *(*(a+i)+j)*(*(a+i)+j)n二维数组元素在内存中的存储形式二维数组元素在内存中的存储形式: :先行后列依次先行后列依次行下标行下标列数列数列下标
14、列下标2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1010二维数组元素的访问n一般要对所有的数组元素执行同样的操作,与一维数一般要对所有的数组元素执行同样的操作,与一维数组类似,用循环结构控制,二维数组需用两层循环组类似,用循环结构控制,二维数组需用两层循环例:例:int a43,n=1,i,j;int a43,n=1,i,j;for(i=0;i4;i+)for(i=0;i4;i+)for(j=0;j3;j+)for(j=0;j3;j+)aij=n+;aij=n+;n程序程序10.110.1 将如下所示的矩阵存入二维数组,然后照原将如下所示的
15、矩阵存入二维数组,然后照原样输出,最后按转置形式输出。样输出,最后按转置形式输出。算法提示算法提示:转置输出不需要另外定义二维数组转置输出不需要另外定义二维数组,只是在控制循只是在控制循环时先控制列下标再控制行下标环时先控制列下标再控制行下标动动态态演示演示过过程程2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1111二维数组与一维数组n二维数组名二维数组名是是二维数组指针二维数组指针常量常量n如果按照递归的概念如果按照递归的概念, ,它也是特殊的一维数组指针它也是特殊的一维数组指针 例:例:int a43;int a43;(1)(1)指针指针
16、a a的基类型为的基类型为int3,aint3,a指向指向a0,a0,即即a= =&a0,a= =&a0,因此因此a+ia+i指向指向ai,ai,即:即:a+i=&ai,a+i=&ai,a+ia+i或或&ai&ai称为称为行指针行指针地址计算公式为地址计算公式为: a+i=a+ i*sizeof (二维数组元素类型二维数组元素类型*列数列数)(2)(2)指针指针a aii的基类型为的基类型为intint,aiai指向元素指向元素ai0,ai0,即即ai= =&ai0,ai= =&ai0,因此因此ai+jai+j指向元素指向元素aij,aij,即即: ai+j= =&aij,: ai+j= =&
17、aij,aiai、* *(a+i)(a+i)、ai+jai+j或或&aij&aij称为称为列指针列指针或或一维指针一维指针地址计算公式为地址计算公式为: ai+jai+j =ai+j*sizeof (二维数组元素类型二维数组元素类型)0i32009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1212二维数组与一维数组n一级指针一级指针也称为也称为列指针列指针或或一维指针一维指针,这是一级指针在,这是一级指针在针对行指针或二维数组指针时的称谓针对行指针或二维数组指针时的称谓n程序程序10.210.2 二维数组行指针和列指针的区别二维数组行指针和列指针的
18、区别提示:提示:a a与与a0a0的值虽然相等,但基类型不同,因此注意比的值虽然相等,但基类型不同,因此注意比较较a+1a+1与与a0+1a0+1的不同值的不同值 (在(在VC+VC+下演示程序)下演示程序)n结论结论1 1:一个一个m m行行n n列的二维数组可以作为长度为列的二维数组可以作为长度为m*nm*n的的一维数组,一维数组,二者在内存中的存储顺序一致二者在内存中的存储顺序一致n程序程序10.310.3 把二维数组当作一维数组输出把二维数组当作一维数组输出算法提示算法提示:用一层循环而不是二层循环控制,注意换行条件用一层循环而不是二层循环控制,注意换行条件动动态态演示演示过过程程20
19、09.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1313二维数组与一维数组n结论结论2 2:一个长度为一个长度为n n的一维数组可以作为的一维数组可以作为1 1行行n n列二维列二维数组数组n例如:例如:double d5=1,2,3,4,5;double d5=1,2,3,4,5;n这里指针这里指针d d的基类型为的基类型为double,double,而指针而指针(& &d d)的基类型的基类型是是double5double5(参看(参看5.2.35.2.3节),相当于节),相当于1 1行行5 5列二维双列二维双浮点型数组指针浮点型数组指针 n程序
20、程序10.410.4 一维数组可以看作行数为一维数组可以看作行数为1 1的二维数组。的二维数组。算法提示算法提示: ( & &一维数组名一维数组名) 相当于二维数组名相当于二维数组名动动态态演示演示过过程程注意:这里的注意:这里的括号不能少括号不能少2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1414二维数组名的双重含义(选讲)n含义一:含义一:整个二维数组变量空间的名称整个二维数组变量空间的名称, ,在执行字节计在执行字节计算算sizeofsizeof和取址运算和取址运算& &时,时,a a就是整个二维数组空间标就是整个二维数组空间标识符,
21、即二维数组变量的名称识符,即二维数组变量的名称 例:例:int a43,int a43,则则a a的类型为的类型为int 43int 43sizeof(a)sizeof(a)的值是的值是4848,&a+1&a+1比比&a&a大大48 48 n含义二:含义二:行一维数组指针,称为行一维数组指针,称为二维数组指针二维数组指针,也称,也称行指针行指针,因为数组变量不能通过其名称直接引用数组,因为数组变量不能通过其名称直接引用数组元素,因此二维数组名称元素,因此二维数组名称“退化退化”了,大部分时候都了,大部分时候都是这一含义。是这一含义。2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼
22、俞琼俞琼 王立柱王立柱王立柱王立柱1515二维数组与行指针 n二维数组要传址,可以传递二维数组要传址,可以传递二维数组指针二维数组指针n二维数组指针的二维数组指针的基类型基类型由由二维数组元素类型和列数二维数组元素类型和列数两两部分部分联合表示联合表示n因此,接受二维数组指针的指针变量,其基类型也应因此,接受二维数组指针的指针变量,其基类型也应该由两部分联合表示,而且对应的部分完全一致,这该由两部分联合表示,而且对应的部分完全一致,这样的指针变量称为样的指针变量称为行指针变量行指针变量 例:例:intint (*p) (*p)33; ;/行指针变量行指针变量p pintint a4 a433=
23、1,2,3,4,5,6,7,8,9,10,11,12;=1,2,3,4,5,6,7,8,9,10,11,12;p=a;p=a;/将二维数组指针赋值给行指针变量将二维数组指针赋值给行指针变量此时行指针变量此时行指针变量p p等价于二维数组指针等价于二维数组指针a a,有以下等价式:有以下等价式:p+i= =a+ip+i= =a+i pi= =ai pi= =aipij= =aijpij= =aij 对应于二维数对应于二维数组元素类型组元素类型对应于二维对应于二维数组的列数数组的列数还可以:还可以:p=a+ip=a+i或或p=&ai,p=&ai,保证保证p p得到的是行指针都是正确的得到的是行指针
24、都是正确的此处的括号此处的括号一定要有一定要有! !2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1616二维数组与行指针 n程序程序10.510.5 将给定矩阵按转置形式输出。将给定矩阵按转置形式输出。本程序与程序本程序与程序10.210.2功能类似,但作了简化,二维数组元素功能类似,但作了简化,二维数组元素初初始化始化给定,不需要输出原始矩阵。给定,不需要输出原始矩阵。本程序用本程序用DisplayDisplay函数实现矩阵转置输出函数实现矩阵转置输出重点理解如何用重点理解如何用行指针变量行指针变量作为形参接受二维数组实参。作为形参接受二维
25、数组实参。n注意:注意:此题的函数原型可以有以下三种等效表示:此题的函数原型可以有以下三种等效表示:(1 1)void Display( void Display( int (*pa)3,int (*pa)3,int row);int row);(2 2)void Display( void Display( int pa3,int pa3,int row);int row);(3 3)void Display( void Display( int pa43,int pa43,int row);int row); 后两种本质上就是第一种形式,且后两种形式只能出现在形后两种本质上就是第一种形式,
26、且后两种形式只能出现在形参表中,不能作为参表中,不能作为行指针变量行指针变量的定义(或声明)形式的定义(或声明)形式 动动态态演示演示过过程程2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1717二维数组与列指针n一个一个m m行行n n列二维数组,可以看作是长度为列二维数组,可以看作是长度为m*nm*n的一维数的一维数组组, ,因此二维数组可以因此二维数组可以传址给列指针传址给列指针例:例:int a43;int a43;则则a0a0(或(或* *a a或或&a00&a00)是指向第)是指向第1 1个二维数组元素个二维数组元素a00a00的指
27、针常量,它等价于长度为的指针常量,它等价于长度为1212的的一维整型数组指一维整型数组指针针,该一维数组的,该一维数组的1212个元素依次为:个元素依次为:a00a00、a01a01a011a011此时存在此时存在等式等式:a0i*3+j=aij a0i*3+j=aij 因此,可以通过定义一个因此,可以通过定义一个列指针(一级指针)列指针(一级指针)变量来接受变量来接受a0a0的值,的值,例如:例如:int *p=a0;int *p=a0;则则 pi*3+j=aij pi*3+j=aij n这样,这样,二维数组也可以通过将其起始列地址传给一个二维数组也可以通过将其起始列地址传给一个一级指针变量
28、来访问所有的元素一级指针变量来访问所有的元素行下标行下标列数列数列下标列下标2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1818二维数组与列指针n程序程序10.610.6 寻找矩阵中的马鞍点。一个矩阵中的元素,寻找矩阵中的马鞍点。一个矩阵中的元素,若在它所在的若在它所在的行中最小行中最小,在它所在的,在它所在的列中最大列中最大,则称,则称为马鞍点。求一个为马鞍点。求一个n*mn*m阶矩阵的所有马鞍点。阶矩阵的所有马鞍点。 算法思想:算法思想:用一个用一个 n n行行m m列二维数组列二维数组a a来存储矩阵,一个长度来存储矩阵,一个长度为为n
29、 n的一维数组的一维数组minmin存储每行中的最小元素,一个长度为存储每行中的最小元素,一个长度为m m的的一维数组一维数组maxmax存储每列中的最大元素。存储每列中的最大元素。寻找马鞍点的具体方法是:寻找马鞍点的具体方法是:用行控制外层循环,在用行控制外层循环,在i i行其行行其行中最小元素为中最小元素为min imin i,在行固定的情况下,用列控制内层,在行固定的情况下,用列控制内层循环,用每一列的最大元素值循环,用每一列的最大元素值maxjmaxj与当前行的与当前行的minimini去比去比较,如果二者相等,则说明一个二维数组元素较,如果二者相等,则说明一个二维数组元素aijaij
30、就是就是马鞍点。马鞍点。显然,显然,一个矩阵中可能不止一个马鞍点,也有可能没有马鞍一个矩阵中可能不止一个马鞍点,也有可能没有马鞍点。马鞍点元素加括号输出。点。马鞍点元素加括号输出。动动态态演示演示过过程程2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱1919一维指针数组与二级指针n所谓所谓一维指针数组,一维指针数组,就是数组元素为就是数组元素为一级指针变量一级指针变量的的一维数组。一维数组。例:例:char* a5;char* a5;a a是是长长度度为为5 5的的一一维维字字符符型型指指针针数数组组,a a是是指指针针常常量量,一一维维数数组
31、组元元素素a0a0、a1a1、a2a2、a3a3、a4a4都都是是一一级级字字符符型型指指针针变量,它们各自可以指向一维字符数组,特别是字符串变量,它们各自可以指向一维字符数组,特别是字符串对每个元素(一级指针变量)都可以赋值对每个元素(一级指针变量)都可以赋值:a0=File; a0=File; a1=Edit; a2=Compile; a3=Run; a1=Edit; a2=Compile; a3=Run; a4=Tools; a4=Tools; 也可以在定义一维指针数组时进行初始化,如普通一维数组也可以在定义一维指针数组时进行初始化,如普通一维数组char* a5=File,Edit,C
32、ompile,Run,Tools;char* a5=File,Edit,Compile,Run,Tools;或或char* a=File,Edit,Compile,Run,Tools;char* a=File,Edit,Compile,Run,Tools;注意:注意:此处不能加括号:而此处不能加括号:而char(*a)5char(*a)5是是1 1个行指针定义个行指针定义2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2020一维指针数组与二级指针n一维指针数组名可以赋值给何种类型的变量?一维指针数组名可以赋值给何种类型的变量?回顾:回顾:一级指
33、针变量与一维数组的关系一级指针变量与一维数组的关系Type arraysizeType arraysize;/数组数组arrayarray的元素类型为的元素类型为TypeType ,即数,即数组指针的基类型为组指针的基类型为TypeTypeType* p; Type* p; /指针变量指针变量p p的基类型为的基类型为TypeType因此:因此:p=array;p=array; / /指针变量指针变量p p指向数组指向数组arrayarray 如果有指针数组定义如果有指针数组定义:char* a5char* a5,则数组,则数组a a的元素类型是的元素类型是char*char*,即数组指针常量
34、,即数组指针常量a a的基类型是的基类型是char*char*,则接受则接受a a值的指值的指针变量的基类型也应该是针变量的基类型也应该是char*char*,故该指针变量类型是故该指针变量类型是char*char*,称为(字符型),称为(字符型)指针的指针指针的指针,也称,也称二级指针二级指针 于是:于是:char *pa=a;char *pa=a;这时,这时,paipai与与aiai等效等效,都是指向某一个字符串的首地址,都是指向某一个字符串的首地址papa为二级为二级指针变量指针变量a a为一维指为一维指针数组名针数组名2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞
35、琼 王立柱王立柱王立柱王立柱2121一维指针数组与二级指针n程序程序10.710.7 主函数中定义指针数组处理多个字符串,函数以主函数中定义指针数组处理多个字符串,函数以指针指针的指针为形参的指针为形参输出所有字符串的值。输出所有字符串的值。输出函数原型输出函数原型:void Display( void Display( char* pachar* pa,int n),int n);另一种形式另一种形式:void Display(void Display(char* pa ,char* pa ,int n);int n);n二级指针、一级指针与普通变量的关系:二级指针、一级指针与普通变量的关系
36、:例例: : char ch= char ch=A A; ; /定义一个普通字符型变量定义一个普通字符型变量char* p=&ch; char* p=&ch; /一级指针变量一级指针变量p p指向了变量指向了变量chchchar* q=&p; char* q=&p; /二级指针变量二级指针变量q q指向了一级指针指向了一级指针p p则对字符值的访问形式有等效的则对字符值的访问形式有等效的3 3种形式:种形式:chch、* *p p、*q,q,如下图所示如下图所示动动态态演示演示过过程程这种形式的形参本质这种形式的形参本质上就是上就是char* pachar* paq qp pchch0x12f
37、f78 0x12ff78 0x12ff7c 0x12ff7c A A&p&p&ch&ch、* *q q* *p p、*q q2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2222一维指针数组与二维数组 n一维指针数组一维指针数组是元素为一级指针变量的一维数组。每是元素为一级指针变量的一维数组。每一个一级指针变量可以分别指向长度不同、且彼此空一个一级指针变量可以分别指向长度不同、且彼此空间不相邻的一维数组。间不相邻的一维数组。n二维数组二维数组是元素为一级指针常量的一维数组。每一个是元素为一级指针常量的一维数组。每一个指针常量分别指向长度相同、彼
38、此空间相邻的一维数指针常量分别指向长度相同、彼此空间相邻的一维数组,组,例:例: char char cColor47=cColor47=“whitewhite”, ,”redred”, ,”orangeorange”, ,”pinkpink” ; ;char *pColor4= char *pColor4= “whitewhite”, ,”redred”, ,”orangeorange”, ,”pinkpink”; cColorcColor是二维数组,其元素为是二维数组,其元素为cColor0cColor3,cColor0cColor3,它们都它们都是是长度为长度为7 7的字符型一维数组的字
39、符型一维数组,且在内存中连续存放,且在内存中连续存放pColorpColor是一维指针数组,其元素为是一维指针数组,其元素为pColor0pColor3,pColor0pColor3,它它们都是们都是一级指针变量一级指针变量,可以指向各独立存放的串首地址,可以指向各独立存放的串首地址2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2323一维指针数组与二维数组w wh hi it te e 00r re ed d00o or ra an ng ge e00p pi in nk k00cColorcColorcColor0cColor0cColor
40、1cColor1cColor2cColor2cColor3cColor3pColorpColorpColor0pColor0pColor1pColor1pColor2pColor2pColor3pColor3white0white0red0red0orange0orange0pink0pink0这这4 4个个字符串字符串长度相长度相等地址等地址相邻相邻这这4 4个字符串个字符串长度不相等长度不相等地址不一定地址不一定相邻相邻多个字符串的处理,既可以用二维字多个字符串的处理,既可以用二维字符数组,又可以用一维指针数组,后符数组,又可以用一维指针数组,后者是更常用的处理方式。者是更常用的处理方式。
41、 2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2424一维指针数组与二维数组 n指针数组的每一个元素作为指针变量,可以指向二维指针数组的每一个元素作为指针变量,可以指向二维数组的行数组,当然,要保证基类型的一致性。数组的行数组,当然,要保证基类型的一致性。n前面的例示中,可以用以下循环实现赋值:前面的例示中,可以用以下循环实现赋值:nfor (i=0;i4;i+)for (i=0;i4;i+)n pColori=cColori; pColori=cColori; n程序程序10.810.8 指针数组和二维数组。指针数组和二维数组。 用二维整型
42、数组存储一个矩阵,通过一维指针数组输出矩阵用二维整型数组存储一个矩阵,通过一维指针数组输出矩阵n指针数组的元素是指针变量,不仅可以指向静态数组指针数组的元素是指针变量,不仅可以指向静态数组n也可以指向动态数组也可以指向动态数组 例:例:int* p4int* p4,i;i; for (i=0;i4;i+) pi=for (i=0;i4;i+) pi=(int*)malloc(3*sizeof(int);(int*)malloc(3*sizeof(int); 动动态态演示演示过过程程2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2525二维动态空
43、间的申请与释放(选讲)n一一级级指指针针可可以以申申请请动动态态一一维维数数组组空空间间,同同理理,二二级级指指针可以申请动态二维数组空间针可以申请动态二维数组空间,需要分两步走:,需要分两步走:n用二级指针申请动态二维数组的方法是:用二级指针申请动态二维数组的方法是: (1 1)首先用二级指针申请一维指针数组空间,指针数组的)首先用二级指针申请一维指针数组空间,指针数组的长度就是动态二维数组的行数;长度就是动态二维数组的行数;(2 2)接着用这些一级指针变量分别申请动态一维数组空间,)接着用这些一级指针变量分别申请动态一维数组空间,其元素个数就是动态二维数组的列数。其元素个数就是动态二维数组
44、的列数。n释放动态二维数组空间的方法是释放动态二维数组空间的方法是( (与申请顺序相反与申请顺序相反):):(1 1)用一层循环首先释放所有由一级指针所申请的动态空)用一层循环首先释放所有由一级指针所申请的动态空间间先释放二维数组元素空间先释放二维数组元素空间 (2 2)再直接通过二级指针变量释放一维指针数组空间)再直接通过二级指针变量释放一维指针数组空间后释放一维指针数组的空间后释放一维指针数组的空间2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2626array00 array01 array02 二维动态空间的申请与释放(选讲) n程序程
45、序10.910.9 通过二级指针变量通过二级指针变量arrayarray申请了申请了rowrow行行colcol列的动态列的动态二维数组空间,二维数组的元素为二维数组空间,二维数组的元素为099099之间的随机数。最后以之间的随机数。最后以矩阵形式输出该动态二维数组。矩阵形式输出该动态二维数组。 关键语句:关键语句:int *arrayint *array,row,col; row,col; array=(int *)malloc(row*sizeof(int *); array=(int *)malloc(row*sizeof(int *); for (i=0;irow;i+) for (i
46、=0;irow;i+) arrayi=(int *)malloc(col*sizeof(int); arrayi=(int *)malloc(col*sizeof(int); 现在:现在:arrayijarrayij就与静态数组元素一样进行访问了就与静态数组元素一样进行访问了动动态态演示演示过过程程申请一维指针数组空间申请一维指针数组空间, ,该该数组含数组含rowrow个元素个元素再用这再用这rowrow个一级指针分别申请个一级指针分别申请colcol个二维数组元素空间个二维数组元素空间arrayarrayarray0array0array1array1array10 array11 arr
47、ay12若若row=2row=2,一维指针数组空间,一维指针数组空间, ,该数组含该数组含2 2个一级指针元素个一级指针元素若若col=3col=3,这是,这是array0array0申请申请的一维整型数组的一维整型数组, ,该数组含该数组含3 3个个intint型元素型元素若若col=3col=3,这是,这是array1array1申请申请的一维整型数组的一维整型数组, ,该数组含该数组含3 3个个intint型元素型元素这这6 6个便是用二级指针申个便是用二级指针申请的动态二维数组元素请的动态二维数组元素2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王
48、立柱王立柱2727二维(数组)指针和一维(数组)指针的相互转化 下下表表总总结结了了第第5 5章章所所讲讲的的一一级级指指针针与与一一维维数数组组、本本章章所所讲讲的的行行列列指指针针与与二二维数组,指针数组及指针的指针之间的关系。维数组,指针数组及指针的指针之间的关系。指针名称指针名称指针定义举例指针定义举例数组定义举例数组定义举例可进行的赋值可进行的赋值基类型基类型一级指针一级指针( (列指针列指针) )int *p;int a10;int m=2;int a43;p=a; p=a+i; p=&ai;p=&m;p=&aij; p=ai;p=*(a+i);int行指针行指针int (*p)3
49、;int a43;int arr3;p=a; p=a+i; p=&ai;p=&arr;int3二级指针二级指针int *p;int *a3;p=a; p=a+i; p=&ai;int *指针数组指针数组int *p4;char *s4;int a43;char b47=”white”,”red”,yellow”,”green”;pi=ai;Si=bi;int *char*2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2828二维(数组)指针和一维(数组)指针的相互转化 n二维数组中的行列指针及相互转化二维数组中的行列指针及相互转化例例: :in
50、t a43;int a43;则行指针有则行指针有: :a a、a+ia+i、&ai &ai 列指针有:列指针有:* *a a、* *(a+i)(a+i)、aiai、ai+jai+j、 &aij&aij 二二维维数数组组元元素素的的表表示示有有:aij aij 、(* *(a+i)(a+i))jj、* *(ai+j)(ai+j)、 * *(*(a+i)+j)(*(a+i)+j) 转化方法:转化方法:行变列,加行变列,加* *号;列变行,取址号;列变行,取址& &n这这种种转转化化方方法法与与一一维维数数组组元元素素与与其其地地址址的的相相互互转转化化规规则则一一样样!(地址到值,加(地址到值,加
51、* *号;值到地址,取址号;值到地址,取址& &)例:例: int a4;int a4;元素的地址有:元素的地址有: a a、 a+ia+i、&ai&ai元素值的表示方法有:元素值的表示方法有: * *a a、 * *(a+i)(a+i)、aiai地址值是:地址值是:&ai0&ai0地址值是:地址值是:&aij&aij2009.8 2009.8 朱立华朱立华朱立华朱立华 俞琼俞琼俞琼俞琼 王立柱王立柱王立柱王立柱2929进入夏天,少不了一个热字当头,电扇空调陆续登场,每逢此时,总会想起进入夏天,少不了一个热字当头,电扇空调陆续登场,每逢此时,总会想起那一把蒲扇。蒲扇,是记忆中的农村,夏季经常用
52、的一件物品。记忆中的故那一把蒲扇。蒲扇,是记忆中的农村,夏季经常用的一件物品。记忆中的故乡,每逢进入夏天,集市上最常见的便是蒲扇、凉席,不论男女老少,个个手持乡,每逢进入夏天,集市上最常见的便是蒲扇、凉席,不论男女老少,个个手持一把,忽闪忽闪个不停,嘴里叨叨着一把,忽闪忽闪个不停,嘴里叨叨着“怎么这么热怎么这么热”,于是三五成群,聚在大树,于是三五成群,聚在大树下,或站着,或随即坐在石头上,手持那把扇子,边唠嗑边乘凉。孩子们却在周下,或站着,或随即坐在石头上,手持那把扇子,边唠嗑边乘凉。孩子们却在周围跑跑跳跳,热得满头大汗,不时听到围跑跑跳跳,热得满头大汗,不时听到“强子,别跑了,快来我给你扇
53、扇强子,别跑了,快来我给你扇扇”。孩。孩子们才不听这一套,跑个没完,直到累气喘吁吁,这才一跑一踮地围过了,这时子们才不听这一套,跑个没完,直到累气喘吁吁,这才一跑一踮地围过了,这时母亲总是,好似生气的样子,边扇边训,母亲总是,好似生气的样子,边扇边训,“你看热的,跑什么?你看热的,跑什么?”此时这把蒲扇,此时这把蒲扇,是那么凉快,那么的温馨幸福,有母亲的味道!蒲扇是中国传统工艺品,在是那么凉快,那么的温馨幸福,有母亲的味道!蒲扇是中国传统工艺品,在我国已有三千年多年的历史。取材于棕榈树,制作简单,方便携带,且蒲扇的表我国已有三千年多年的历史。取材于棕榈树,制作简单,方便携带,且蒲扇的表面光滑,因而,古人常会在上面作画。古有棕扇、葵扇、蒲扇、蕉扇诸名,实即面光滑,因而,古人常会在上面作画。古有棕扇、葵扇、蒲扇、蕉扇诸名,实即今日的蒲扇,江浙称之为芭蕉扇。六七十年代,人们最常用的就是这种,似圆非今日的蒲扇,江浙称之为芭蕉扇。六七十年代,人们最常用的就是这种,似圆非圆,轻巧又便宜的蒲扇。蒲扇流传至今,我的记忆中,它跨越了半个世纪,圆,轻巧又便宜的蒲扇。蒲扇流传至今,我的记忆中,它跨越了半个世纪,也走过了我们的半个人生的轨迹,携带着特有的念想,一年年,一天天,流向长也走过了我们的半个人生的轨迹,携带着特有的念想,一年年,一天天,流向长长的时间隧道,袅长的时间隧道,袅结束