C语言程序设计第8章-指针课件.pptx

上传人(卖家):三亚风情 文档编号:3514992 上传时间:2022-09-10 格式:PPTX 页数:81 大小:1.19MB
下载 相关 举报
C语言程序设计第8章-指针课件.pptx_第1页
第1页 / 共81页
C语言程序设计第8章-指针课件.pptx_第2页
第2页 / 共81页
C语言程序设计第8章-指针课件.pptx_第3页
第3页 / 共81页
C语言程序设计第8章-指针课件.pptx_第4页
第4页 / 共81页
C语言程序设计第8章-指针课件.pptx_第5页
第5页 / 共81页
点击查看更多>>
资源描述

1、8 8.1.1 指针的基本概念指针的基本概念8 8.2.2 指针指针与数组与数组8.3 8.3 指针指针与函数与函数第第八八章章 指针指针8.4 8.4 知识知识点强化与点强化与应用应用8 8.5.5 本章本章小结小结【学习要点】1.指针的基本概念2.指针与数组3.指针与函数本章主要介绍指针的基本概念,指针与数组的关系及应用,指针与函数的关系及应用。指针是C语言的特色,希望大家能学好该部分内容,实现如函数中多数据的返回等C语言其他部分不能实现的功能。正确使用指针,能写出紧凑高效的程序。定义学生信息管理系统中的某个子模块的功能,实现从键盘输入一个班级中所有学生的某门课程的成绩,通过调用函数实现统

2、计,按规定格式输出最高分、最低分、平均分,同时输出优秀人数、良好人数、及格人数、不及格人数以及所占比例。【导入案例:函数中多数据的返回】在前面我们所讲的函数中,只能有一个返回值,参数之间只能是实参的值传递给形参,实现的是单向传递。程序中要求返回最高分、最低分、平均分以及各分数段的人数及所占比例等多个返回值。如何使函数能有多个返回值呢?这就需要用到指针。分析正确使用指针,必须深入地学习和掌握指针的概念。可以说,没掌握指针就是没有掌握C语言的精华。8.1 指针的基本概念8.1.1指针的概念8.1.2 指针变量的定义与初始化8.1.3 指针的引用及运算8.1.4 指针变量作为函数参数8.1 指针的基

3、本概念8.1.1指针的概念1地址及取地址运算符在程序中定义了一个变量,系统会根据变量的类型为变量分配相应字节的存储空间,用于存放数据,存放的数据称为内存单元的内存单元的内容内容,而系统为变量分配的存储空间的首个存储单元的地址称为变变量的地址量的地址。可按如下的方式获取变量的地址:&变量名变量名&是单目运算符,称为取地址运算符取地址运算符,其操作数是变量名。8.1.1指针的概念(续)1地址及取地址运算符例如:int a=10;则&a是整型变量a的首地址。利用存储空间的地址,可以访问存储空间,从而获得存储空间的内容。地址就好像是一个路标,指向存储空间。因此,又把地址形象地称为指针指针。8.1.1指

4、针的概念(续)1地址及取地址运算符0012FF56H10a内容地址8.1.1指针的概念(续)2指针变量 在C语言中,专门用来存放地址的变量称为指针变量指针变量,指针指针变变量的量的值为地址值为地址。假设pa是存放整型变量地址的变量,如有语句 int a=10,*pa;pa=&a;8.1.1指针的概念(续)即a的地址存入变量pa,则称“指针变量pa指向变量a”,或“pa是a的指针”,被pa指向的变量a称为“pa的对象”。“对象”就是一个有名字的内存区域,即一个变量。这时,对变量a的访问就有两种方式,分别是直接通过变量a来访问和通过指向a的指针变量pa来访问。8.1.1指针的概念(续)指针类型是对

5、所有类型的指针的总称,指针的类型指针的类型是指针变量所指对象的数据类型。例如,pa是指向整型变量的指针,简称整型指针。整型指针是基本类型的指针之一,除各种基本类型之外,允许说明指向数组的指针、指向函数的指针、指向结构和联合(第九章会讲)的指针以及指向各类指针的指针。地址是指针变量的值,也称为指针,指针变量有时也简称为指针,因此,指针指针一词可以指地址值、指针变量,还可以是地址和指针变量二者。8.1.2 指针变量的定义与初始化1指针变量的定义 指针的定义形式为:存储存储类型说明类型说明 数据类型数据类型 *指针变量名指针变量名;说明:(1)指针说明和一般变量说明语法相似,只是在变量之前都有“*”

6、符号。(2)“*”后面的名字是指针变量名,指针变量名遵循C语言标识符命名规则。(3)指针的数据类型,是指针所指向的变量的数据类型,而不是指针自身的数据类型,指针变量本身只能装地址值,显然只属于整型范畴。(4)“void*”的指针变量,在使用前可临时强制转换成相应的对象类型。8.1.2 指针变量的定义与初始化(续)2指针变量的初始化 指针变量初始化的一般形式为:存储存储类型说明类型说明 数据类型数据类型 *指针变量名指针变量名=初始地址值;初始地址值;说明:(1)赋值号前面的部分为指针的定义,在定义的同时立刻赋值。(2)初始地址值通常为如下形式:int x,*px=&x;(3)初始地址值最好不要

7、为具体的十六进制的整数,因为不知该地址是否可用。8.1.2 指针变量的定义与初始化(续)(4)指针类型虽然可装整型数据,但注意指针变量不能存放一般的整型数,这个数必须是合理、可用的内存地址。一个一般的整型数代表的地址未必合理,也未必可用,因为如果在代码区,会造成程序崩溃,而在ROM区则不可用。(5)可以把指针初始化为空指针。例如:在头文件stdio.h中,有如下定义:#define NULL 0 可以定义:int*p=NULL;8.1.3 指针的引用及运算1指针的引用 在引用指针变量时,可能有3种情况:(1)给指针变量赋值。如:pa=&a;即把a的地址赋给指针变量pa,又称pa指向a。(2)引

8、用指针变量指向的变量。如果已执行“pa=&a;”,即指针变量pa指向了整型变量a,则:printf(%d,*p);其作用是以整数形式输出指针变量p所指向的变量的值,即变量a的值。8.1.3 指针的引用及运算(续)2指针的运算(1)&:取地址运算符。&a是变量a的地址。(2)*:指针运算符,又称“间接访问”运算符。*p代表指针变量p指向的对象。指针运算符“*”的作用与取地址运算符“&”完全相反,两者互为逆运算。例如表达式:*&i 运算过程说明如下:由“&”计算变量i的存储区地址,后由“*”作用于该地址i,求出存放在该地址的变量的内容。注意注意:“*”与“&”具有相同的优先级别并且是自右向左的结合

9、方向。指针也可以作为函数参数,传递地址值。当常量、普通变量、表达式、数组元素作函数参数时,实参与形参之间是单向的数值传递,函数调用时把实参传递给形参,形参通常是局部动态临时变量,形参的改变对实参没有任何影响,因此不能企图改变形参的值而达到处理实参的目的,它的影响是单向的。利用指针,我们能够通过函数调用的形式改变主调函数实参值。实参与形参变量共用一个内存空间,都可以引用其值,也都可以对它进行修改,指针作参数对值的影响是双向的。8.1.4 指针变量作为函数参数【例例8-1-4-1 8-1-4-1】通过子函数】通过子函数swap()swap(),实现两整型变量的数据交换。,实现两整型变量的数据交换。

10、分析:只能使用指针作函数参数,才能实现双向传递。参考程序如下:#include void swap(int*pa,int*pb);void main()int a=10,b=20;printf(a,b交换前的值分别为:%d,%d的n,a,b);swap(&a,&b);printf(a,b交换后的值分别为:%d,%d的n,a,b);void swap(int*pa,int*pb)int t;t=*pa;*pa=*pb;*pb=t;指针变量作为函数参数时,它的影响是双向的,在主调函数和子函数之间可传递多个值。这是地址传递的一个优点。说明:(1)若采用了地址值传递的方式,可不用return语句,通过

11、内存共用,也能够达到主调函数和子函数之间传递值的目的。(2)当函数需要返回多个值时,用return语句不能做到,因为return语句只能返回一个值。这时可以设置一些空的或初始化后的指针变量作为函数参数,达到返回多个值的目的。【例例8-1-4-2 8-1-4-2】统计一行正文中字母、数学、其他字符的个数。统计一行正文中字母、数学、其他字符的个数。分析:本题要返回三个值,用return语句不能做到。须定义有三个指针或地址值作为参数,通过共用内存,即主函数和子函数都可操作同一存储空间来达到传递值的目的。参考程序如下:#include#include void count(char s,int*pa,

12、int*pb,int*pc);void main()char s20;int a=0,b=0,c=0;printf(请输入一串字符:n);gets(s);count(s,&a,&b,&c);printf(此串字符中,字母为%d个,数字为%d个,其他字符为%d个n,a,b,c);void count(char s,int*pa,int*pb,int*pc)char c;int i;for(i=0;i=a&si=A&si=0&si=9)+*pb;else+*pc;指针与数组是C语言中很重要的两个概念,它们之间有着密切的关系,利用这种关系,可以增强处理数组的灵活性,加快运行速度。8.2 指针与数组8

13、.2.1 指针与一维数组8.2.2 指针与二维数组8.2.3 指针与字符串8.2.4 指针数组8.2.5 指向指针的指针8.2.6 指针数组作main函数的参数 8.2 指针与数组8.2.1 指针与一维数组 C语言中规定数组名是一个地址常量。而指针是地址变量,它们可以很好地结合在一起。1数组的指针表示如果我们想用一个指针指向数组a,则必须首先定义一个指针,并且该指针指向的数据类型应与数组a的元素类型一致,即:int a10;int*pa;pa=a;数组名指向数组的首元素,即数组名中存放了数组中第一个元素的地址值,即数组的首地址。也就是该数组所占一串连续存储单元的起始地址。8.2.1 指针与一维

14、数组(续)下面的语句也可以完成指针pa指向数组a的操作:pa=&a0;/等价于“pa=a;”对于上述指向数组a的指针变量pa,若pa的值为数组a的首地址,则表达式pa+i与表达式a+i所表达的含义一致,即ai的地址,此时也可以说pa+i指向ai,或者说pa+i为ai的指针。说明:(1)运算符实际上完成变址运算,即将ai按a+i计算地址,然后找出此单元的内容。(2)任何指向数组元素的指针变量在引用数组时,除可以用指针形式*(pa+i)引用外,也可以像数组一样通过下标引用数组元素,如pai与*(pa+i)。【例【例8-2-1-1】把把一个字符串的字符逆序输出。一个字符串的字符逆序输出。分析:通过指

15、针加上整数运算,先使指针p指向最后一个字符,再输出p所指向的字符,每次循环p指针减1。参考程序如下:#include#includevoid main()char s=abcdefghijk;char*ps;int i;printf(字符串为:n%sn,s);printf(字符串的倒序为:n);for(ps=s+strlen(s)-1;ps=s;ps-)printf(%c,*ps);printf(n);8.2.1 指针与一维数组(续)2引用数组元素有三种形式(1)下标法,如通过ai引用。(2)指针法,通过数组名计算数组元素的地址来引用数组元素,如*(a+i)。(3)指针法,利用指向数组的指针变

16、量pa,如*(pa+i)或pai。8.2.1 指针与一维数组(续)虽然指针和数组关系非常密切,几乎所有引用数组的场合都可以用指向它的指针来替代,但指针和数组又是完全不同的两个概念。说明:(1)pa是指针变量,它的值可以改变,如“pa+=3;”及“pa+;”等都是正确的表达式语句。(2)a是地址常量,“a+=3;”及“a+”等却为非法,因为a是常量,它的值在系统为其定义时就已确定,即编译系统为数组a分配的起始地址。(3)只有当指向数组a的指针pa的值为数组的首地址时,*(pa+i)或pai才和ai等价。当pa的值不指向数组的首地址时,则它们就不完全等价。例如:pa=a+2;此后,则pa0相当于a

17、2,pa-2相当于a0,pa3相当于a5。8.2.1 指针与一维数组(续)3对数组赋值,可采用指向数组元素的指针运算方法和下标方法。如pa指向a0,则可通过给*(pa+i)、*pi或pi赋值,从而给数组元素ai赋上新值。4在使用指针变量引用数组元素时,需要注意指针变量的运算问题,特别是对于运算符“+”与“-”使用的前后次序。说明:(1)表达式“*p+”表示等价于*(p+),即“+”运算是作用于指针而不是指针的对象。因为单目“*”和“+”是同一优先级,按从右至左结合的运算符。不同于(*p)+。后者是将p所指对象的值加1。(2)要注意*p+的含义是表示先取*p的值,再使p指向下一个元素。而表达式“

18、*+p”表示先使p指向下一个元素再取其所指对象的值。【例【例8-2-1-2】有一个数组有一个数组x,存放,存放10个学生的成绩,求平均成绩。要求个学生的成绩,求平均成绩。要求通过通过指针指针变量来访问数组元素。变量来访问数组元素。分析:定义数组x10来存放10个学生成绩。通过指针加上整数运算,先使指针p指向第一个成绩,每次循环p指针加1。通过指针间接访问求和。参考程序如下:#include void main()float x10;float sum=0.0,aver,*px;int i;px=x;printf(请输入10个学生的成绩:(以空格分开)n);for(i=0;i10;i+)scan

19、f(%f,px);px+;for(px=x;px=x+9;px+)sum+=*px;aver=sum/10.0;printf(10个学生的平均成绩为:%6.2fn,aver);8.2.2 8.2.2 指针指针与二维数组与二维数组 对于多维数组,我们也可以使用指针来描述。二维数组使用较多。1通过地址来引用二维数组元素 例如,定义一个3行4列的二维数组a:int a34=1,2,3,4,5,6,7,8,9,10,11,12;可以这样理解:a是数组名,数组a中含有由3个一维数组组成的行元素a0、a1和a2构成,而a0、a1和a2又分别是三个一维数组的起始地址。同样,我们也可以将a0看成一个一维数组的

20、数组名,由一维数组指针变量表示法,数组元素aij的地址可写为ai+j,而由一维数组与指针的关系可知,ai与*(a+i)完全等价,所以ai+j也可以写成*(a+i)+j。又因ai+j代表&aij,所以*(a+i)+j与&aij等价。8.2.2 8.2.2 指针指针与二维数与二维数组组(续)归纳来看,对于数组a34,有以下5种表示二维数组元素以及相应地址的方法:二维数组元素表示方法二维数组元素地址表示方法 aij&aij *(ai+j)ai+j *(*(a+i)+j)*(a+i)+j (*(a+i)ja0+4*i+j *(&a00+4*i+j)&a00+4*i+j8.2.2 8.2.2 指针指针与

21、二维数与二维数组组(续)2通过一个指向二维数组的指针变量来引用二维数组 指向二维数组的指针变量与指向一维数组的指针变量用法相似。定义指针后,将二维数组的首地址赋给指针即可。对于二维数组,可以像处理一维数组一样用指向数组元素的指针变量,即“按列变化的指针”,这是我们使用较多的情况。【例例8-2-2-1】使用指向数组元素的指针变量引用数组,对一个使用指向数组元素的指针变量引用数组,对一个3行行4列的列的整型整型数组数组赋值并按照赋值并按照3行行4列的格式对齐输出列的格式对齐输出。分析:定义3行4列的数组a和一个指针p,使p指向a,利用for循环通过p来对数组a进行操作。参考程序如下。#includ

22、e void main()int a34,*p;int i,j,k=1;p=&a00;/使指针指向数组a的首地址for(i=0;i3;i+)/给数组元素赋值for(j=0;j4;j+)*p=k;p+;k+;p=&a00;/指针再次指向数组a的首地址printf(数组a如下:n);for(i=0;i3;i+)/输出数组for(j=0;j4;j+)printf(%5d,*p+);printf(n);/换行 8.2.2 8.2.2 指针指针与二维数与二维数组组(续)(续)3通过建立一个行指针来引用二维数组 在C语言中,二维数组可以看作由多个一维数组构成,因此,我们可以定义一个指向由n个元素组成的数组

23、的指针变量,然后用该指针指向其中的一个一维数组,即所谓的用“行指针”处理二维数组。“行指针”定义的一般形式为:存储存储类型说明类型说明 数据类型数据类型 (*数组名)数组名)下标下标;说明:(1)“下标”为二维数组中每一行中元素的个数,即与列下标同值。即定义了一个指针,该指针包含与二维数组中一行相同个数的元素。(2)定义中的圆括号是必须的,否则成为了指针数组。8.2.2 8.2.2 指针指针与二维数与二维数组组(续)(续)例如:int a34,(*pp)4;pp=a;二维数组的每一行相当于一个一维数组。这里定义了一个指针变量pp包含4个整型元素的一维数组,通过赋不同的地址值,p就指向了二维数组

24、的不同行,因此pp又称为“行指针”。这里pp指向二维数组a的首行,表达式pp+i的含义相当于a+i,即指针指向二维数组的第i行。同二维数组元素的地址计算规则相对应,它们也有如下等价形式:1)ppij等价于aij。2)*(ppi+j)等价于*(ai+j)。3)*(*(pp+i)+j)等价于*(*(a+i)+j)。不同的是:ppi的值是可变的,而ai的值是不可变的。【例例8-2-2-2】使用行指针引用二维数组使用行指针引用二维数组。分析:定义3行4列的数组a和一个行指针数组(*p)4,使指针p指向a。该程序中p是一个指针,它指向含有4个元素的一维数组。通过p指针来对数组a进行引用。参考程序如下。#

25、include void main()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int(*p)4,i;p=a+1;/给指针赋值printf(%5d,%5dn,p11,*(p1+2);8.2.3 指针与字符串 字符数组通常用来存放字符串,指针指向数组也就指向了字符串,因此通过指针可以引用它所指向的字符串。1指向字符串指针变量的定义及赋值 定义的一般形式如下:存储存储类型说明类型说明 char char*指针变量;指针变量;如:char*p1,*p2=abcde;以上的定义中p2在定义的同时直接赋了初值”abcde。如果已经定义了一个字符型指针变量,也可以:char*p

26、1;p1=abcde;这里也是将存放字符串常量abcde的首地址赋给了指针变量p1。8.2.3 指针与字符串(续)2字符指针的引用 当一个字符型指针变量指向了某个字符串后,就可以利用指针变量来处理这个字符串。主要有两种处理方式:(1)整体处理字符串 输出字符串:printf(“%s”,指针变量);或puts(指针变量);输入字符串:scanf(“%s”,指针变量);或gets(指针变量);(2)单个处理字符串中的字符 第i个字符的格式为:*(指针变量+i);这里也是将存放字符串常量abcde的首地址赋给了指针变量p1。【例例8-2-3-18-2-3-1】利用指针实现两个字符串的连接。利用指针实

27、现两个字符串的连接。分析:指针p指向第一个串末尾(最后一个字符的后面),指针指向第二个串的首部。将第二个串中字符依次放入第一下串后。参考程序如下:#include#include void main()char str120,str220,*p,*q;printf(Input the two strings:n);printf(str1=);gets(str1);printf(str2=);gets(str2);p=str1+strlen(str1);/*p指向第一个字符串的末尾q=str2;while(*q!=0)*p=*q;p+;q+;*p=0;printf(str1+str2=);put

28、s(str1);8.2.4 指针数组 针对二维数组可以看作由多个一维数组构成的特点,我们可以定义一个由多个指针构成的指针数组,让该指针数组中的每一个指针元素指向一个一维数组。可以通过建立一个指针数组来引用二维数组。当一个数组的元素类型为某种指针类型时,该数组就称为指针数组。1指针数组的定义形式为:存储存储类型说明类型说明 数据类型数据类型 *数组名数组名 下标下标;说明:(1)“下标”表示该数组元素的个数,应与所指向的数组的行下标同值,即所指向的数组有多少行,该语句就定义多少个指针元素。(2)数据类型指明指针数组的元素能指向的对象的类型。8.2.4 指针数组(续)(3)数组名前的*是必需的,由

29、于它出现在数组名之前。方括号的运算级别高于指针运算符,因此数组名先与下标结合,再与*结合,即先定义数组名是一个一维数组,再确定该数组的类型为指针类型。(4)指针数组的定义可以和其他变量及数组的定义出现在同一个定义语句中。例如:int*p3,a34,i,j;定义指针数组p,它有3个元素,每个元素都是指向int型变量的指针变量。和一般数组定义一样,数组名p是第一个元素即p0的地址,也是地址常量。8.2.4 指针数组(续)若满足条件0i3,则pi和ai的基类型相同,pi=ai是合法的赋值表达式。若有以下循环:for(i=0;i3;i+)pi=ai;则循环的执行结果使p0、p1、p2分别指向数组a每行

30、的开头。这时,数组aij的引用形式*(ai+j)和*(pi+j)是完全等价的。由此可见,可通过指针数组p来引用二维数组a。它们的等价形式如下:1)pij等价于aij。2)*(pi+j)等价于*(ai+j)。3)*(*(p+i)+j)等价于*(*(a+i)+j)。!注意:pi的值是可变的,而ai的值是不可变的。8.2.4 指针数组(续)指针数组的主要用途是表示二维数组,尤其是字符串数组。用指针数组表示二维数组的优点是:二维数组的每一行或字符串数组中的每一个字符串可以具有不同的长度,用指针数组表示字符串数组处理起来十分方便灵活。8.2.4 指针数组(续)2用指针数组表示多维数组 用指针数组表示二级

31、数组在效果上与数组的下标表示是相同的,只是表示形式不同。用指针数组表示时,需要额外增加用作指针的存储开销;但用指针方式存取数组元素比用下标速度快,而且每个指针所指向的数组元素的个数可以不相同。用指针数组表示二维数组就是用指针表示二维数组,只是用指针数组更直观、更方便而已。用指针数组表示二维数组的方法可以推广到三维以上数组。例如,对于三维数组来说,指针数组元素的个数应与左边第一维的长度相同,指针数组的每个元素指向的是一个二维数组,而且每个二维数组的大小也可以不同。指针数组应用最多的是描述由不同长度的字符串组成的数组。【例例8-2-4-18-2-4-1】输入一个表示月份的整数,输出该月份的名字。输

32、入一个表示月份的整数,输出该月份的名字。分析:定义一个字符指针数组,每个指针指向一个表示月份的英文字符串,根据输入的月份值,输出对应的指针所指向的字符串。参考程序如下:#include#include void main()char *monthname=January,February,March,April,May,June,July,August,Septempber,October,November,December;int i;printf(Please input the number of month:n);scanf(%d,&i);if(i=1&i=12)printf(%sn,

33、monthnamei-1);else printf(%s,Error,Illegal month!);printf(n);8.2.4 指针数组(续)4指针数组和字符串数组的比较 由指针数组monthname所表示的一组字符串可以用下面的字符串数组来表示:char month11=January,February,March,April,May,June,July,August,Septempber,October,November,December;二者的表达效果相同,但它们之间的存储结构不同。8.2.4 指针数组(续)说明:(1)用字符串数组表示时每一字符串的存储长度相同,说明时必须明确指出

34、每一字符串的存储长度,均为最长字符串的长度加1,这里为11。用指针数组表示时每一个字符串的存储长度可以各不相同,说明时没有字符串的长度说明,各字符串的长度由初值字符串中含有的字符个数加1确定。因此指针数组比字符串数组节省空间。(2)字符串数组表示中,指针monthi等同一个数组名,值为该字符串的首地址。指针数组表示中,指针monthnamei是存放字符串首地址的变量。即数组名monthi等同于指针名monthnamei。8.2.5 8.2.5 指向指向指针的指针的指针指针 指针数组和指针的指针是C语言中较为深入的部分,两者之间关系密切。一个指针变量可以指向一个整型、实型、字符型数据,也可以指向

35、一个指针型数据。这就是所谓指向指针变量的指针变量,简称指针的指针。由于指针数组的每一个元素都是指针型的变量,其值为地址。因此,指针的指针经常与指针数组联系在一起。如图8-2-4-2所示,monthname是一个指针数组,它的每一个元素是一个指针型的变量,其值为地址。monthname既然是一个数组,它的每一元素都应有相应的地址。数组名monthname代表该指针数组首元素的地址。monthname+i是monthnamei的地址。monthname+i就是指向指针型数据的指针,也即指针的指针。8.2.5 8.2.5 指向指向指针的指针的指针指针 (续)说明:(1)单级指针。指针的值就是基本类型

36、变量的地址,这可以称为单级间接寻址,亦即单级指针。(2)多级指针。一个指针中存放的是另一个指针的地址,而另一个指针中存放的又可能是别的指针变量的地址,直到最后一级指针才指向其所指向变量的地址,这种通过多级指针访问变量的方式称为多级间接寻址,亦即多级指针。(3)C语言中这种多级指针寻址可以延伸到所需要的任何一级,但因为寻址级数过多会使程序跟踪困难,容易造成混乱,所以在实际编程中以二级指针,即指向指针的指针为最简单和最常用的形式。8.2.5 8.2.5 指向指向指针的指针的指针指针 (续)我们可以定义多级指针,但是这里以常用的二级指针作为要点介绍其定义形式:存储类型说明存储类型说明 数据类型数据类

37、型 *指针变量名指针变量名 ;有定义如下:char*p;由于*运算符的结合性从右到左的原则,所以*p相当于*(*p),即char*p,可以把它分为两部分看:char*和(*p),后面的(*p)表示p是指针变量,前面的char*表示p指向的是char*型的数据,也就是说,p指向一个字符指针变量(这个字符指针变量指向一个字符型数据)。【例例8-2-5-18-2-5-1】使用指向指针数据的指针变量。使用指向指针数据的指针变量。分析:定义一个指针数组monthname,并对它初始化,使monthname数组中的每一个元素分别指向一个字符串。定义一个指向指针型数据的指针变量p,使p先后指向monthna

38、me数组中各元素,输出这些元素所指向的字符串。参考程序如下。#include void main()char*monthname=January,February,March,April,May,June,July,August,Septempber,October,November,December;char*p;int i;for(i=0;i12;i+)p=monthname+i;printf(%sn,*p);8.2.6 8.2.6 指针指针数组作数组作mainmain函数的函数的参数参数 表示和处理main函数的参数是指针数组和多级指针的一个重要应用。前面章节所举例子的程序中main函数

39、都没有参数,实际上,支持C的系统允许main函数可以有两个参数;也可以处理由main返回的值,一般为正常终止时返回值为0,非正常终止返回值1。main函数的参数习惯上用名字argc和argv表示,前者是一个int类型整数,后者是一个字符指针数组。有参数的main函数定义为:intint main(main(intint argc,charargc,char *argvargv)函数体函数体 main函数由操作系统调用,它的实参来源于运行可执行C程序时在操作系统环境下键入的命令行,称为命令行参数。8.2.6 8.2.6 指针指针数组作数组作mainmain函数的函数的参数参数(续)可执行的C程序

40、文件的名字是操作系统环境下的一个外部命令(DOS)或shell命令(UNIX环境)的名字,命令名是由argv0指向的字符串。在命令名之后输入的参数是由空格隔开的若干个字符串,依次由argv1、argv2、所指示。每个参数字符串的长度可以不同,参数的数目任意。操作系统的命令解释程序将这些字符串的首地址构成一个字符指针数组,并将指针数组元素的个数(包括第0个元素)传给main函数的形参argc(argc的值至少为1);指针数组的首地址传给形参argv,所以argv实际上是一个二级字符指针变量。【例例8-2-6-18-2-6-1】回显命令行参数。回显命令行参数。分析:许多操作系统提供了echo命令,

41、它的作用是实现“参数回送”,即将后面的各参数(各字符串)在同一行上输出。实现程序(文件名为echo.c)如下:#include void main(int argc,char*argv)int i;for(i=1;iargc;i+)printf(%sc,argvi,(iargc-1)?:n);也可以将程序改为如下形式:#include void main(int argc,char*argv)while(argc1)+argv;printf(%s%c,*argv,(argc1)?:n);-argc;printf(n);在Visual C+环境下对程序编译和连接后,选择“工程”“设置”“调试”,

42、在“程序变量”后输入“How are you?”说明:(1)命令行参数的个数(含命令名称echo)argc的值为5。其中argv0指向“echo”,argv1指向“How”,,argv4指向“?”。(2)假定经编译、连接后生成的可执行文件的名字为echo.exe(DOS环境)或echo(UNIX环境),在操作系统环境下输入下面的命令行并按回车:echo How are you?则输出:How are you?C语言程序的基本单位是函数,函数经过编译后,其目标代码在内存中是连续存放的,该代码的首地址即为函数的入口地址。函数名本身代表该函数的入口地址,如果使用变量来描述,我们称其为函数的指针,它的

43、值等于函数的入口地址,通过此指针变量可以实现对该函数的调用。这是我们调用函数的又一方法。在需要大量调用子函数时,我们可以通过指向函数的指针来快速调用。8.3 指针与函数8.3.1 指向函数的指针 8.3.2 返回指针的函数 8.3 指针与函数8.3.18.3.1指向函数的指向函数的指针指针1指向函数的指针的定义与引用 指向函数的指针变量(通常简称函数指针变量)定义形式如下:存储存储类型说明类型说明 数据类型数据类型 (*指针变量名)();指针变量名)();例如:int(*p)();其中的p被定义为指向一个返回值是整型量的函数说明:(1)数据类型可以是基本类型或所定义的其他类型。(2)定义中第一

44、对圆括号是必需的,如果去掉,就成为int*p(),含义为:p是一个返回值为指向整型量指针的函数。8.3.18.3.1指向函数的指向函数的指针指针(续)(3)指向函数的指针变量不能进行算术运算、关系运算。(4)让一个指向函数的指针变量指向某一函数时,只需将函数的函数名赋值给该指针变量,而不要带上相应的函数参数,也不需要带括号,例如,函数原型为int countstr(char*s),则应该是func=countstr,而不应该是func=countstr(str);显然后一种情况赋值号右边就是一次函数调用,得到的应该是当参数为str时的函数值,所以这种赋值是错误的。定义一个指向函数的指针变量,仅

45、表示定义了一个专门用来存放函数入口地址的指针变量,在程序中只要将某一个函数的地址赋给它,它就指向相应的函数。【例8-3-1-1】输入任意一串英文字符,此句最多100个字符,请统计其中字符x出现的次数及字符串中字符的总个数。分析:(1)在主函数中定义一个指向函数的指针变量func,通过给func赋值为countx来将函数countx的入口地址赋给指针变量,因此,通过调用函数(*func)(str)来达到与调用countx(str)一样的效果。(2)通过给func赋值为countall来将函数countall的入口地址赋给指针变量,从而达到调用另一函数的目的。参考程序如下:#include int

46、 countx(char*s)/统计字符串中x的个数 int number=0;while(*s!=0)if(*s=x)number+;s+;return(number);int countall(char*s)/统计字符串中所有字符的总个数 int number=0;while(*s!=0)number+;s+;return(number);void main()char str101;int(*func)(char*);/定义指向函数的指针变量funcscanf(%s,str);func=countx;/将函数的地址赋给funcprintf(x的个数为:%dn,(*func)(str);f

47、unc=countall;/将函数的地址赋给funcprintf(所有字符个数为:%dn,(*func)(str);8.3.18.3.1指向函数的指向函数的指针指针(续续)2指向函数的指针变量作函数参数 指向函数的指针变量作为参数传递到其他函数,是函数指针的重要用途。被调用函数可以通过函数的指针来调用完成不同功能的具体函数。【例8-3-1-2】输入两个数a、b,按输入的字符串来决定对它们的操作:当字符串开始两个字符为“-s”时,用函数max(a,b)找出两数中的最大值,否则调用函数sum(a,b)求两个数的和。最后输出结果。分析:输入两个数及小于5个字符的一个字符串。局部变量flag起一个标志

48、作用,初值为0,当输入的字符串的开始字符为“-s”时,则置flag的值为1。定义一个函数指针process,当flag的值为1时,指针指向max(a,b)函数,否则指针指向sum(a,b)函数,从而实现调用不同函数的目的。参考程序如下:#include#include int max(int x,int y)return(xy?x:y);int sum(int x,int y)return(x+y);int caller(int x,int y,int(*process)(int,int)return(*process)(x,y);void main()int a,b,result;int f

49、lag=0;char c5,*p=c;printf(请输入一个小于5个的字符串:n);gets(c);if(*p=-&*(p+1)=s)flag=1;printf(请输入a,b的值:);scanf(%d%d,&a,&b);result=caller(a,b,(flag?max:sum);printf(结果为%dn,result);8.3.2 8.3.2 返回返回指针的函数指针的函数 一个函数可以返回一个int型、float型、char型的数据,也可以返回一个指针类型的数据。返回指针值的函数简称为指针函数,正如返回整型的函数简称为整型函数一样。指针函数的定义格式如下:存储存储类型说明类型说明 数

50、据类型数据类型 *函数名(形参表)函数名(形参表)函数体函数体 例如定义:int*f(int x,int y)8.3.2 8.3.2 返回返回指针的指针的函数函数(续续)说明:(1)在函数名的两侧分别是函数运算符()和指针运算符*,但由于()的优先级高于*,因此函数名先与()结合成一个函数,再与*结合成返回指针值的函数,即返回的是一个地址值。(2)用法上,返回指针值函数与其他类型返回值一样。要注意的是在return语句中,返回的必须为一个地址值,而且类型必须与定义的返回值类型一致。!注意!注意:不能将指针函数说明符*f(int,int)写成函数指针说明符(*f)(int,int)。【例【例8-

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

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(C语言程序设计第8章-指针课件.pptx)为本站会员(三亚风情)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|