樊媛媛《c语言程序设计》10-指针.ppt

上传人:小飞机 文档编号:5992284 上传时间:2023-09-12 格式:PPT 页数:68 大小:231.50KB
返回 下载 相关 举报
樊媛媛《c语言程序设计》10-指针.ppt_第1页
第1页 / 共68页
樊媛媛《c语言程序设计》10-指针.ppt_第2页
第2页 / 共68页
樊媛媛《c语言程序设计》10-指针.ppt_第3页
第3页 / 共68页
樊媛媛《c语言程序设计》10-指针.ppt_第4页
第4页 / 共68页
樊媛媛《c语言程序设计》10-指针.ppt_第5页
第5页 / 共68页
点击查看更多>>
资源描述

《樊媛媛《c语言程序设计》10-指针.ppt》由会员分享,可在线阅读,更多相关《樊媛媛《c语言程序设计》10-指针.ppt(68页珍藏版)》请在三一办公上搜索。

1、第十章 指针 指针:C的一个重要概念、重要特色。它使C具备了强大的功能,使C成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。不掌握指针等于没有掌握C语言的精华。,101 指针的概念 简单地说,指针就是地址。要掌握指针的概念就必须弄清:内存地址概念?变量与地址的关系?如何通过地址进行变量的存取?,说明例:内存用户数据 1000 3 i 1002 6 j 1004 9 k对变量值的存取总是按地址进行的-直接访问。,int i,j,k;i=3;j=6;k=i+j;,程序经编译后,变量名就不复存在,以地址对应。,也可以采用“间接访问”方式:先将变量i的地址存

2、放到另一变量p1中,要访问i时,先取出p1的内容(变量i的地址),再去访问该地址所对应的内存单元中的内容(变量i的值)。,内存用户数据 1000 3 i 1002 6 j 1004 9 k 2000 1000 p1 2004 1002 p2,int i,j,k;i=3;j=6;k=i+j;int*p1,*p2;p1=,在以上概念的基础上对指针下定义:变量的地址就是该变量的指针。存放地址的变量称指针变量。若p1存放了变量i的地址,则称p1是指向变量i的指针变量。,int i,j,k;i=3;j=6;k=i+j;int*p1,*p2;p1=,102 变量的指针和指向变量的指针变量 变量的指针 指针

3、变量 指向变量的指针变量 用“*”代表“指向”如*p1代表它所指向的变量i,同一内存单元。以下两个语句等价:i=3;直接访问*p1=3;间接访问int i,*p1;p1=,内存用户数据 1000 3 i 1002 6 j 1004 9 k 2002 1000 p1 2004 1002 p2,int i,j,k;i=3;j=6;k=i+j;int*p1,*p2;p1=,5,8,指针变量的定义 指针变量也必须先定义后使用。int*p1;注意:*表示该变量为指针变量,但变量名是p1。一个指针变量只能指向同一类型的变量。int i,*p1;float a;p1=不合法,指针变量的引用 两种用法:用地址

4、运算符 不允许 使用指针运算符*之前,p1必须被赋值(即p1必须存放了某个变量的地址),例:T10-1.c 注意:要区别定义和引用中的“*”main()int a=100,b=10;int*p1,*p2;定义指针变量,尚无体指向 p1=,运算结果:*p1=100,*p2=10&a=12ff7c,&b=12ff78p1=12ff7c,p2=12ff78&p1=12ff74,&p2=12ff70,要特别注意以下用法的后果:egp1.c int*p1;*p1=100;,例:输入a和b两个整数,按先大后小的顺序输出 main()T10-2.c int a,b,*p1,*p2,*p;scanf(“%d,

5、%d”,2004 p2 2006 p 改变p1和p2的指向,1000,1002,1002,1000,1000,重要概念:只要将某一变量的地址存入指针变量中,就可通过指针变量间接访问该变量。配钥匙!,swap(int p1,int p2)int t;t=p1;p1=p2;p2=t;1000 5 a 1002 9 b main()int a,b;scanf(“%d,%d”,2006 t T10-3-1.c,5,9,5,9,5,例 不用指针变量作函数参数,将两个整数按大小顺序输出。,怎样直接修改a、b的值呢?,修改原件用指针!,指针变量作为函数的参数 可将指针变量作函数的参数,接受实参地址,获得具体

6、指向,进而通过指针变量间接访问主调函数的变量。,例T10-3.c用指针变量作函数参数,将两个整数按大小顺序输出。swap(int*p1,int*p2)int t;t=*p1;*p1=*p2;*p2=t;1000 5 a 1002 9 b main()int a,b;scanf(“%d,%d”,2006 t,1000,1002,5,9,5,重要概念:使用指针变量作函数参数,被调函数可以将多个结果交给主调函数。数组名做参数,可返回该数组所有元素 还记得那个求成绩最高、最低和平均值的例子?还需要用全局变量吗?,例T10-4-2.c:求n个数的最大值、最小值和平均值。float aver(int a,

7、int n,int*max,int*min)int i;float s=0;*max=a0;*min=a0;for(i=0;i*max)*max=ai;if(ai*min)*min=ai;return(s/100);,main()int a100,i,max,min;float av;for(i=0;i100;i+)scanf(“%d”,例T10-4-1.c:编写函数,求一元二次方程的两个实根。#include“math.h”?root(float a,float b,float c,)float d;d=b*b-4*a*c;if(d0|a=0)return(0);?=(-b+sqrt(d)/

8、2/a;?=(-b-sqrt(d)/2/a;return(1);,float*x1,float*x2,*x1,*x2,int,main()int k;float a,b,c,x1,x2;scanf(“%f,%f,%f”,输入:1,-10,25输出:5.000000,5.000000,函数参数:如不需改变(只读):一般参数如需改变(读写):指数参数,103 数组的指针和指向数组的指针变量数组有一个首地址:数组的指针。每个数组元素也都有地址:数组元素的指针。,5,3,2,1,6,8,7,4,2000,2002,2004,2006,指向数组元素的指针变量 int a10,*p;p=a;指向数组 p=

9、指向数组元素,5,1,2,4,7,6,8,0,3,9,2000,2002,2004,2006,p,通过指针引用数组元素 int a10,*p;p=其中p+1指向a1注意:p+1不是地址加1,而是加一个数据类型单位。,一般地,当p指向a0时,即p=,举例:用三种方法输出数组元素例T10-5-1.c 用“数组名+下标”的方法main()int i,a5;for(i=0;i5;i+)scanf(“%d”,输入:55 66 77 88 99,输出:&a0=ffce,a0=55&a1=ffd0,a1=66&a2=ffd2,a2=77&a3=ffd4,a3=88&a4=ffd6,a4=99,举例:用三种方

10、法输出数组元素例T10-5-2.c 计算“数组名计算地址”的方法main()int i,a5;for(i=0;i5;i+)scanf(“%d”,a+i);for(i=0;i5;i+)printf(“a+%d)=%x,*(a+%d)=%d n”,i,(a+i),i,*(a+i);,输出:(a+0)=ffcc,*(a+0)=55(a+1)=ffce,*(a+1)=66(a+2)=ffd0,*(a+2)=77(a+3)=ffd2,*(a+3)=88(a+4)=ffd4,*(a+4)=99,举例:用三种方法输出数组元素例T10-5-3_new.c 用“指针变量+下标”的方法(指针法I)main()in

11、t*p,a5,i;p=a;for(i=0;i5;i+)scanf(“%d”,p+i);for(i=0;i5;i+)printf(,输出:&p0=12ff6c,p0=55,*(p+0)=55&p1=12ff70,p1=66,*(p+1)=66&p2=12ff74,p2=77,*(p+2)=77&p3=12ff78,p3=88,*(p+3)=88&p4=12ff7c,p4=99,*(p+4)=99,举例:用三种方法输出数组元素(例T10-5-4_new.c)用“指针变量指向数组元素”法(指针法II)main()int*p,a5;for(p=a;p(a+5);p+)scanf(“%d”,p+i);f

12、or(p=a;p(a+5);p+)printf(“p=%x,*p=%d n”,p,*p);,输出:p=12ff6c,*p=55p=12ff70,*p=66p=12ff74,*p=77p=12ff78,*p=88p=12ff7c,*p=99,p+:合法,因p是指针变量,而变量可以用+运算符的a+:不合法,因为a是数组名,其值是数组元素的首地址,分配之后不可变。,举例:用三种方法输出数组元素(例T10-5-4.c)指针变量当作数组名使用(混合指针法)main()int a5,*p=a,i;for(p=a;pa+5;p+)scanf(“%d”,p);p=a;/不能漏!for(i=0;i5;i+)pr

13、intf(“,输出:&p0=12ff6c,p0=55,*(p+0)=55&p1=12ff70,p1=66,*(p+1)=66&p2=12ff74,p2=77,*(p+2)=77&p3=12ff78,p3=88,*(p+3)=88&p4=12ff7c,p4=99,*(p+4)=99,通过指针引用数组元素的方法小结例:累加求和的各种用法:int*p,a10;s=0;p=a;for(i=0;i10;i+)s+=ai;for(i=0;i10;i+)s+=*(a+i);for(i=0;i10;i+)s+=*(p+i);for(i=0;i10;i+)s+=pi;for(i=0;i10;i+)s+=*p+;

14、for(p=a;pa+10;p+)s+=*p;最后一种用法效率高。,数组元素地址法,指针法I指针变量指向数组元素,指针法II指针变量当作数组名注意不能使用a+,指针变量使用时的几个问题,若p当前指向a数组的第i个元素,则:10-plus.c*p:是取出ai的值.p+:指针指向ai+1.*p+:等价于*(p+)及ai+,优先级同为2,从右向左结合,将 ai 的值取出,后再使 p增1(不是单纯的加一,是p指向ai+1).*(+p):与a+i等价,先将p指向ai+1,然后将该元素取出.(*p)+:将p所指的数组元素ai的值取出,使ai的值增1.p-:指针指向ai-1.*(p-):与ai-等价,将p

15、所指向的第i个数组元素取出,然后使p指向i-1元素.*(-p):与a-i等价,先将p减1指向第i-1个元素,然后将其取出.(*p)-:将p所指的数组元素ai的值取出,使ai的值减1.,数组名作为函数参数 有了指针概念的基础上,重新回顾数组名作为函数参数时,数据的传递情况:void sort(int a,int n)void sort(int*a,int n),例:选择法排序函数,void sort(int*a,int n)例T10-7-1.c int i,j,t;for(i=0;iaj)t=ai;ai=aj;aj=t;只将形参改为指针变量,仍按下标法使用,void sort(int*a,int

16、 n)int i,j,t;for(i=0;i*(a+j)t=*(a+i);*(a+i)=*(a+j);*(a+j)=t;按指针法使用例T10-7-2.c,进一步优化:都用指针,效率更高!(例T10-7-3.c)void sort(int*a,int n)int*i,*j,t;for(i=a;i*j)t=*i;*i=*j;*j=t;main()int a10,j;for(j=0;j10;j+)scanf(“%d”,a+j);sort(a,10);for(j=0;j10;j+)printf(“%5d”,aj);,分段排序?例T10-7-4.c main()int a10,j;for(j=0;j10

17、;j+)scanf(“%d”,a+j);for(j=0;j10;j+)printf(“%5d”,aj);,sort(a,5);,sort(a+5,5);,void sort(int*a,int n)int*i,*j,t;for(i=a;i*j)t=*i;*i=*j;*j=t;,指向多维数组的指针和指针变量 从本质上说,多维数组的指针与一维数组的指针相同,但在概念上和使用上,多维数组的指针要复杂些。以二维数组的指针为例:,二维数组的地址:一维:a,&ai,a+i 二维:aa+i(行指针:指向第i行)ai*(a+i)(特殊的一维数组,列指针,指向行中的列)ai+j*(a+i)+j&aij,int

18、a34,a0,讨论以下用法的效果:T10-8-1.cfor(i=0;i3;i+)scanf(“%d”,a+i);输入数据:1 2 3,讨论以下用法的效果:T10-8-2.cfor(i=0;i3;i+)scanf(“%d”,a1+i);输入数据:1 2 3,讨论以下用法的效果:T10-8-3.cfor(i=0;i3;i+)scanf(“%d”,a1+i+2);输入数据:1 2 3,讨论以下用法的效果:T10-8-4.cfor(i=0;i3;i+)scanf(“%d”,a+i+1);输入数据:1 2 3,a0+1,a0+2,a0+3,一维数组与二维数组的比较,第i个一维数组的第j个元素的地址,无意

19、义,*(a+i)+j,第i个一维数组的第j个元素的值,无意义,*(*(a+i)+j),第i个一维数组的值第i个一维数组的首地址,第i个元素的值,*(a+i),第i个元素 的地址一维数组,第i个元素的地址,a+i,二维数组的首地址,一维数组的首地址,a,二维数组,一维数组,注意:指针运算符*作用在行指针上的结果仍是指针-列指针;*作用在列指针上的结果-具体元素。*(a+0),*(a+1),*(a+2)仍是地址。*(a+i)ai*(a0),*(a1),*(a1)具体元素值。*(ai)*(a+i)+j 也是地址,但要区别:(a+i)+j行指针(a+1)+1?*(a+i)+j列指针*(a+1)+1?,

20、如果要通过a+i形式的地址访问数组元素的具体内容,则:*(*(a+i)或*(*(a+i)+j)如:*(*(a+1)a10*(*(a+1)+2)a12讨论:例T10-8-5.c*(a+2)*(*(a+1)+3)*(a1+1)*(*(a+1)+5),例:求数组a的所有元素之和。可有多种用法:例T10-9-1.cT10-9-3.c M行N列for(i=0;iM;i+)for(i=0;iM;i+)for(j=0;jN;j+)for(j=0;jN;j+)s+=aij;s+=*(ai+j);for(i=0;iM;i+)for(j=0;jN;j+)s+=*(*(a+i)+j);,aij*(ai+j)*(*(

21、a+i)+j),指向二维数组的指针变量 同样可使一个指针变量p指向二维数组a,再通过p访问数组元素。例T10-10.cmain()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int i,k,*p;p=a;k=*p;?k=*(p+2);?for(p=a;pa+2;p+)printf(“%3d,”,*p);?N列:aij*(p+i*N+j)pi*N+j,k=p12;不合法k=*(*(p+1)+2);,k=p1*4+2;合法k=*(p+1*4+2);,例:求矩阵的上三角元素之和。例T10-11.cmain()int a34,*p,i,j,s=0;输入a p=a;for(i=

22、0;i3;i+)for(j=i;j4;j+)s+=pi*4+j;或 s+=*(p+4*i+j)printf(“n%d”,s);/s=54N列:aij*(p+i*N+j)pi*N+j,多维数组的指针作函数参数 用于接受实参数组地址的形参可用两种:行指针和列指针。以方阵转置为例:例T10-13-1.c void at(int(*p)3)用行指针 int i,j,t;缺点:不通用(必须制定列数)for(i=0;i3;i+)for(j=i+1;j3;j+)t=pij;pij=pji;pji=t;p指向一个包含3个整形元素的一维数组(行指针),p相当于一个二维数组!,用列指针:例T10-13-2.c v

23、oid at(int*p,int n)/n为列数 int i,j,t;for(i=0;in;i+)for(j=i+1;jn;j+)t=pi*n+j;pi*n+j=pj*n+i;pj*n+i=t;优点:通用 在编通用函数时,一般使用列指针。,用列指针:例T10-13-3.c int sum(int*p,int m,int n)/m行n列 int i,j,s=0;for(i=0;im;i+)for(j=i;jn;j+)s+=pi*n+j;或 s+=*(p+n*i+j)return(s);优点:通用 在编通用函数时,一般使用列指针。,104 字符串的指针和指向字符串的指针变量 字符串的表示形式 可用

24、两种方法访问字符串:用字符数组存放字符串 用字符指针指向一个字符串,例T10-14.cmain()char str5=”abc”;定义字符数组,并将字符串存入 char*p=str;定义指针变量,指向字符串 printf(“%s”,str);通过数组名访问字符串 printf(“%s”,p);通过指针变量访问字符串 printf(“%c”,*(p+2);通过指针变量访问字符,str,a,b,c,0,a,b,c,0,1000,1000,p,与其它一维数组的指针相比,字符串的指针有其独特之处:可以通过指针对字符串进行整体访问。对字符串的操作依赖于结束符。可以整体赋初值。有各种字符串处理函数。,本节

25、重点掌握:通过数组和通过指针操作字符串的基本方法。常用的字符串处理方法。,例:字符串拷贝操作。例T10-15-1.c,例T10-15-2.cmain()char a=”abcdef”,b20;int i;for(i=0;*(a+i)!=0;i+)*(b+i)=*(a+i);*(b+i)=0;printf(“%s”,b);main()char a=”abcdef”,b20,*p1,*p2;p1=a;p2=b;for(;*p1!=0;p1+,p2+)*p2=*p1;*p2=0;printf(“%s”,b);,用指针变量处理,将拷贝操作编成一函数:例T10-15-3.c,例T10-15-4.cvoi

26、d copy_string(char*from,char*to)for(;*from;from+,to+)*to=*from;*to=0;还可以改成:void copy_string(char*from,char*to)for(;*from;)*to+=*from+;*to=0;,字符串合并函数:例T10-16.c,void append_string(char*from,char*to)for(;*to;to+);for(;*from;)*to+=*from+;*to=0;,阅读程序:例T10-17.cvoid f(char*c)main()c+=2;char c20=”abcdef”;(*

27、c)+;f(c+1);c+;*c=0;printf(“%s”,c);,内存空间的动态分配 在程序设计中,对于要处理的批量数据,我们往往是选用数组作为存放这些数据的数据结构,然而,数组有一个明显的缺点,就是在定义数组时,其长度必须是常值,无法根据需要动态地定义。这样,在很多情况下,不是定义的数组长度不够,就是定义太长以至于浪费。采用动态分配可以克服这一缺点,并且可以随时释放。,动态分配内存空间步骤:定义一指针变量。申请一片内存空间,并将其首地址赋给指针变量。此时便可通过指针变量访问这片内存;不成功则返回地址为0 用完后释放这片内存空间。int*p;p=malloc(字节数);free(p);si

28、zeof(类型):返回该类型数据在当前编译系统中所占的字节数。以上函数的原形在stdio.h中。,p,例:对n个学生的分数排序后输出。例T10-18.c#include“stdio.h”void sort(int*a,int n)main()int*a,j,n;scanf(“%d”,/exit(0):正常运行程序并退出程序/exit(1):非正常运行程序导致退出程序,105 函数的指针和指向函数的指针变量用函数指针变量调用函数可以用指针变量指向一个函数。一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针。可以用指针变量指向函数,然后通过该指针变量调用此函数。,int max(i

29、nt x,int y)int z;if(xy)z=x;else z=y;return(z);main()int(*p)();定义指向函数的指针变量p int a,b,c;p=max;将p指向函数max scanf(“%d%d”,例T10-19.c,把指向函数的指针变量作为函数参数 指向函数的指针变量最常见的用途是把它作为函数的参数,用于接受主调函数传来的某一函数的入口地址,从而在被调函数中可以通过该指针变量调用它所指向的函数,这样,被调函数中就可实现非固定函数的调用,以达到编写通用函数的目的。例:用矩形法编写一个通用的求定积分的函数。关键问题:如何处理被积函数是未知的。,double intg

30、ral(double a,double b,int n,double(*f)()int i;double h,x,y,s=0;h=(b-a)/n;for(i=1;i=n;i+)x=a+(i-1)*h;y=(*f)(x);s+=h*y;return(s);例T10-20.c,double f1(double x)return(3*x*x+2*x-1);main()double s;s=intgral(1.0,2.0,100,f1);,10.8 指针型数据小结,一、有关指针的数据类型(见下表),二、指针运算小结 1、指针变量加减一个整数如:p+p-p+i p-i p+=i p-=i 等实际含义如

31、p+i 代表地址计算:p+c*i,c为字节数,例如字符型c=1。2、指针变量赋值 如:p=&a a为变量,p为指针变量 p=array array为数组名 p=&arrayi p=max max为函数名 p1=p2 p2为指针变量注意:不能把一个整数或常数赋给p,如p=1000 同样也不能把p赋给整型变量,如i=p,3、指针变量可以赋空值如:p=NULL;实际NULL是整数0。4、两个指针变量可以相减 如两个指针变量指向同一个数组的元素(如右图),则 p2-p1=4-1=3但p1+p2无意义。5、两个指针变量比较 若两个指针指向同一个数组的元素,则可以比较,如:p1p2,inv(int x,i

32、nt n)int i,j,m,t;main()m=(n-1)/2;for(i=0;i=m;i+)int a10,i;输入a j=n-1-i;inv(a,10);t=xi;输出a xi=xj;xj=t;,a,x,例T10-6-1.c:将数组a中的n个数按相反顺序存放。,a与x共用同一片内存单元,inv(int*x,int n)指针变量作函数参数时的传递情况int i,j,m,t;main()m=(n-1)/2;for(i=0;i=m;i+)int a10,i;j=n-1-i;输入a t=xi;inv(a,10);xi=xj;输出a xj=t;下标法例T10-6-2.c,a,1000,1000,x,j=n-1-i;t=*(x+i);*(x+i)=*(x+j);*(x+j)=t;指针法例T10-6-3.c,进一步优化:例T10-6-4.c int inv(int*x,int n)main()int*i=x,*j=x+n-1,t;for(;ij;i+,j-)int a10,i;输入a t=*i;inv(a,10);*i=*j;输出a*j=t;优点:简练 效率高,i,j,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号