C语言教程课件Ch10指针1

上传人:无*** 文档编号:185086345 上传时间:2023-02-02 格式:PPT 页数:39 大小:605.50KB
收藏 版权申诉 举报 下载
C语言教程课件Ch10指针1_第1页
第1页 / 共39页
C语言教程课件Ch10指针1_第2页
第2页 / 共39页
C语言教程课件Ch10指针1_第3页
第3页 / 共39页
资源描述:

《C语言教程课件Ch10指针1》由会员分享,可在线阅读,更多相关《C语言教程课件Ch10指针1(39页珍藏版)》请在装配图网上搜索。

1、本章主要内容本章主要内容 指针和地址的概念指针和地址的概念 指针变量指向数组指针变量指向数组/字符串时的操作字符串时的操作 指针变量做函数参数指针变量做函数参数 几种指针类型几种指针类型 返回指针值的函数返回指针值的函数重点、难点重点、难点 如何理解指针和地址的概念如何理解指针和地址的概念 灵活使用指向一位数组灵活使用指向一位数组/字符串的指针字符串的指针 灵活使用指针变量灵活使用指针变量/数组名做函数参数数组名做函数参数 掌握几种指针的概念掌握几种指针的概念 与函数一章的例题结合,掌握参数单向传递的与函数一章的例题结合,掌握参数单向传递的实质实质1地址的概念地址的概念 程序中每一个变量在编译

2、或运行时系统都为其分配内存程序中每一个变量在编译或运行时系统都为其分配内存单元,每一个内存单元单元,每一个内存单元(字节字节)都有一个相应的编号,这个都有一个相应的编号,这个编号称为该内存单元的编号称为该内存单元的“地址地址”,而内存单元中存入的内,而内存单元中存入的内容则是该变量的值。容则是该变量的值。内存用户数据区内存用户数据区36920002000200220043010变量变量 i变量变量 j变量变量 k变量变量 i_ptint i=3,j=6,k=9;int *i_pt;i_pt=&i;指针是指针是c c语言中比较灵活的数据结构语言中比较灵活的数据结构,灵活地运用指针灵活地运用指针可

3、以可以:(1)(1)有效地表示复杂的数据结构有效地表示复杂的数据结构.(2)(2)动态分配内存动态分配内存.(3)(3)更方便地使用字符串和数组更方便地使用字符串和数组.(4)(4)直接处理内存地址直接处理内存地址.2 2对内存单元的存取有两种方式对内存单元的存取有两种方式 (1)(1)直接访问直接访问 按按变量地址变量地址存取变量的值。存取变量的值。(2)(2)间接访问间接访问 将变量将变量i i的地址存放在另一个内存单元的地址存放在另一个内存单元j j中,要访问中,要访问i i,则先按则先按j j的地址取出的地址取出i i的地址,再按的地址,再按i i的地址取出的地址取出i i的值。的值。

4、直接访问和间接访问示意图直接访问和间接访问示意图3i20003ii_pt 20003 3指针变量的概念指针变量的概念 一个一个变量的地址变量的地址称为该变量的称为该变量的“指针指针”。如果有一个变量专门用来存放另一个变量的地址如果有一个变量专门用来存放另一个变量的地址(即指即指针针),则它称为,则它称为“指针变量指针变量”。指针变量的值是指针。指针变量的值是指针。一、指针变量的定义一、指针变量的定义 指针变量必须在使用之前先定义,它是用来存放地址的。指针变量必须在使用之前先定义,它是用来存放地址的。必须将它定义为必须将它定义为“指针类型指针类型”。定义的一般形式为:定义的一般形式为:类型标识符

5、类型标识符 *标识符标识符注注:(1)标识符前面的标识符前面的“*”,表示该变量为指针变量。但指针变,表示该变量为指针变量。但指针变 量名是量名是pt_1、pt_2、pt_3,而不是,而不是*pt_1、*pt_2、*pt_3。(2)*表示表示指向指向,故故*pt_1,*pt_2,*pt_3表示指针变量表示指针变量 pt_1,pt_2,pt_3所指向的变量。所指向的变量。(3)一个指针变量只能指向一个指针变量只能指向同一个类型同一个类型的变量。的变量。int *pt_1;char *pt_2;float *pt_3;二、指针变量的引用二、指针变量的引用 有两个有关的运算符有两个有关的运算符 (1

6、)&取地址运算符取地址运算符 (2)*指针运算符指针运算符(或称或称“间接访问间接访问”运算符运算符)。例例:int a,*pt;&a为变量为变量a的地址的地址,*pt为指针变量为指针变量pt所指向的变量所指向的变量.则则:&*pt=&a=pt 则则:*&a=*pt=a 则则:(*pt)+相当于相当于a+apt *pt若若:pt=&ab=(*pt)+;c=*pt+;b与与c值是否相等值是否相等?void main()int a,b,*p1,*p2;a=100;b=10;p1=&a;p2=&b;printf(%d,%dn,a,b);printf(%d,%dn,*p1,*p2);100,10100

7、,10运行结果运行结果*p1ap1bp2&b*p210010&a例例2:void main()int a,b,*p1,*p2,*p;scanf(%d%d,&a,&b);p1=&a;p2=&b;if(ab)p=p1;p1=p2;p2=p;printf(%d,%dn,a,b);printf(%d,%dn,*p1,*p2);输入:输入:5 9*p1ap1bp2&b*p2 5 9&ap&b&a输出:输出:5,99,5void main()int a,b,*p1,*p2,t;scanf(%d%d,&a,&b);p1=&a;p2=&b;if(ab)t=*p1;*p1=*p2;*p2=t;printf(%d

8、,%dn,a,b);&a*p1*p2三、指针变量作为函数参数。三、指针变量作为函数参数。例例1:输入:输入a和和b两个整数,按先大后小的顺序输出两个整数,按先大后小的顺序输出a和和b。void main()int a,b;int*point_1,*point_2;scanf(%d%d,&a,&b);point_1=&a;point_2=&b;if(ab)swap(point_1,point_2);printf(n%d,%dn,a,b);printf(n%d,%dn,*point_1,*point_2);输入数据输入数据:4 8输出结果输出结果:8,4 8,4void swap(int*p1,i

9、nt*p2)int p;p=*p1;*p1=*p2;*p2=p;a ab bpoint_1point_2&a&b48p1p284point_1point_2&a&bvoid swap(int*p1,int*p2)int *p;p=p1;p1=p2;p2=p;void main()int a,b;int*point_1,*point_2;scanf(%d%d,&a,&b);point_1=&a;point_2=&b;if(ab)swap(point_1,point_2);printf(n%d,%dn,a,b);printf(n%d,%dn,*point_1,*point_2);a b point

10、_1point_2输入数据:输入数据:4 84 8p1p2 point_1point_2输出结果:输出结果:4,84,8注:注:1.1.不能企图通过改变形参地址而使实参地址也改变,不能企图通过改变形参地址而使实参地址也改变,也就是说调用函数也就是说调用函数不能改变不能改变实参指针变量的值。实参指针变量的值。2.2.调用函数调用函数可以改变可以改变实参指针变量实参指针变量所指变量的值所指变量的值。ap1bp2cp3例例2:输入:输入a,b,c 三个整数,按大小顺序输出。三个整数,按大小顺序输出。void swap(int*pt1,int*pt2)int*pt1,*pt2;int p;p=*pt1

11、;*pt1=*pt2;*pt2=p;void exchange(q1,q2,q3)int*q1,*q2,*q3;if(*q1*q2)swap(q1,q2);if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);void main()int a,b,c,*p1,*p2,*p3;scanf(%d%d%d,&a,&b,&c);p1=&a;p2=&b;p3=&c;exchange(p1,p2,p3);printf(n%d,%d,%dn,a,b,c);5103&b&a&cq1q2q3pt1pt210 5q1q2q3一、指向数组元素的指针变量一、指向数组元素的指针变量 与

12、前面介绍的指向变量的指针变量相同。与前面介绍的指向变量的指针变量相同。若:若:int a10,*p;p=&a0;则:则:(1)p+i和和a+i就是就是ai的地址,或者说它们指向数组的第的地址,或者说它们指向数组的第i个个 元素。元素。(2)*(p+i)或或*(a+i)是是p+i或或a+i所指向的数组元素,即所指向的数组元素,即ai。(3)指向数组的指针变量可以带下标,如指向数组的指针变量可以带下标,如pi与与*(p+i)等价。等价。数组的指针是指数组的起始地址,数组元素的指针数组的指针是指数组的起始地址,数组元素的指针是数组元素是数组元素 的地址。的地址。指针法:指针法:main()int *

13、p,i,a10;p=&a0;for(i=0;i10;i+)scanf(%d,p+);printf(n);p=&a0;for(i=0;i10;i+)printf(%3d,*p+);pa0a1a2a9例例1:输出数组全部元素。:输出数组全部元素。(设设a数组,整型,数组,整型,10个元素个元素)3p5pp-4p12pp*(p+i);p+i);p=a;p=a;(2)下标法下标法main()int a10;int i;for(i=0;i10;i+)scanf(%d,&ai);printf(n);for(i=0;i10;i+)printf(%3d,ai);(3)地址法地址法main()int a10;i

14、nt i;for(i=0;i10;i+)scanf(%d,a+i);printf(n);for(i=0;i10;i+)printf(%3d,*(a+i);在使用指针变量时应注意的几个问题:在使用指针变量时应注意的几个问题:1.数组名是数组的首地址,因此数组名是数组的首地址,因此 p=&a0 与与 p=a 等价等价。2指针变量可以实现使本身的值改变,数组名不可以。指针变量可以实现使本身的值改变,数组名不可以。例例:p+正确正确 a+不正确不正确 3要注意指针变量的当前值。要注意指针变量的当前值。4指针变量可以指到数组后的内存单元。指针变量可以指到数组后的内存单元。5注意指针变量的运算,若先使注意

15、指针变量的运算,若先使p指向数组指向数组a(即即p=a),则,则 (1)p+(或或p+=1)指向下一个元素。指向下一个元素。(2)*p+等价于等价于*(p+)先得到先得到p指向的变量的值,指向的变量的值,p再再 加加1。(3)*(p+)与与*(+p)作用不同,前者先取作用不同,前者先取*p,后使,后使p加加 1;后者相反。;后者相反。(4)(*p)+表示表示p所指向的所指向的元素值加元素值加1。(5)若若p当前指向当前指向a数组第数组第i个元素,则:个元素,则:*(p-)相当于相当于ai-,先取,先取p值作值作*运算,再使运算,再使p自减;自减;*(+p)相当于相当于a+i,先使,先使p自加,

16、再作自加,再作*运算;运算;*(-p)相当于相当于a-i,先使,先使p自减,再作自减,再作*运算。运算。二、数组名作函数参数二、数组名作函数参数 用数组名作参数,在调用函数时实际上是把数组的首地址用数组名作参数,在调用函数时实际上是把数组的首地址传给形参,这样实参与形参共同指向同一段内存。因而调用过传给形参,这样实参与形参共同指向同一段内存。因而调用过程中,如形参数组元素值发生变化也就使实参数组的元素发生程中,如形参数组元素值发生变化也就使实参数组的元素发生了变化,但这种变化并不是从形参传回实参的,而是由于形参了变化,但这种变化并不是从形参传回实参的,而是由于形参与实参共享同一段内存而造成的。

17、与实参共享同一段内存而造成的。例例2:将数组:将数组a中中n个整数按相反顺序存放。个整数按相反顺序存放。245760 11973379 11067542imjvoid inv(int x,int n)int i,j,t,m=n/2;for(i=0;im;i+)j=n-1-i;t=xi;xi=xj;xj=t;void main()int i,a10=3,7,9,11,0,6,7,5,4,2;printf(The original array:n);for(i=0;i10;i+);printf(%3d,ai);printf(n);inv(a,10);printf(The array has bee

18、n inverted:n);for(i=0;i10;i+)printf(%3d,ai);printf(n);void inv(int*x,int n)int t,*i,*j;j=x+n-1;for(i=x;ij;i+,j-)t=*i;*i=*j;*j=t;a0a1a2a3a937911067542a4a5a6a7a8a a 数组数组i,xp=x+mj若将形参改为指针,则若将形参改为指针,则inv函数可改为:函数可改为:27911067543ji24911067573ij 如果有一个实参数组,想在函数中改变此数组的元素的如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以

19、下几类情况:值,实参与形参的对应关系有以下几类情况:(1)形参和实参都用形参和实参都用数组名数组名 传递的是实参数组首地址,形参与实参传递的是实参数组首地址,形参与实参共用同一段内存共用同一段内存单元。单元。(2)实参用实参用数组名数组名,形参用,形参用指针变量指针变量 通过指针变量值的改变可以指向实参数组的任一元素。通过指针变量值的改变可以指向实参数组的任一元素。(3)实参和形参都用实参和形参都用指针变量指针变量 先使实参指针变量指向数组的首地址,然后将实参的值先使实参指针变量指向数组的首地址,然后将实参的值 传给形参,通过指针变量值的改变可以使其指向数组的每个传给形参,通过指针变量值的改变

20、可以使其指向数组的每个元素。元素。(4)实参为实参为指针变量指针变量,形参为,形参为数组名数组名 设设p为指针变量,令为指针变量,令p=&a0,p为实参,对应的形参为实参,对应的形参x为为数组名,则函数调用时将数组名,则函数调用时将 p的值传给形参数组名的值传给形参数组名x,也就是使,也就是使其取得其取得 a数组的首地址,使数组的首地址,使 x数组和数组和 a数组共用同一段内存单数组共用同一段内存单元元.例例3:用选择法对:用选择法对10个整数排序。个整数排序。void sort(int x,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;jxk

21、)k=j;if(k!=i)t=xi;xi=xk;xk=t;void main()int*p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d,*p+);(1)实参用实参用指针变量指针变量,形参用,形参用数组名数组名(2)实参用实参用数组名数组名,形参用,形参用指针变量指针变量void sort(int*x,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;j*(x+k)k=j;if(k!=i)t=*(x+i);*(x+i)=*(x+k)

22、;*(x+k)=t;void main()int i,a10;for(i=0;i10;i+)scanf(%d,&ai);sort(a,10);for(i=0;i10;i+)printf(%3d,ai);(3)实参用实参用指针变量指针变量,形参也用,形参也用指针变量指针变量void main()int*p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d,*p+);void sort(int*x,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=

23、i+1;j*(x+k)k=j;if(k!=i)t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;例例4:从:从10个数中找出其中最大值和最小值。个数中找出其中最大值和最小值。int max,min;void main()int i,number10;void max_min_value();printf(enter 10 datan);for(i=0;i10;i+)scanf(%d,&numberi);max_min_value(number,10);printf(n max=%d,min=%d,max,min);方法方法1:外部变外部变量量void max_min_value(

24、int array ,int n)int*p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;pmax)max=*p;else if(*pmin)min=*p;number 2 32 -12 4 56 7 28 -67 39 41arrayarray_endp22maxmin32p-12pp 56ppp-67ppp*array void main()int i,number10;int amax,amin,*amax_p,*amin_p;void max_min_value();printf(enter 10 datan);f

25、or(i=0;i10;i+)scanf(%d,&numberi);amax=amin=number0;amax_p=&amax;amin_p=&amin;max_min_value(number,10,amax_p,amin_p);printf(max=%d,min=%dn,*amax_p,*amin_p);方方法法2:2:amaxaminamax_pamin_p12-23 5 78 27 6 9 36 3 41212 void max_min_value(int array,int n,int*a1,int*b1)int i;for(i=1;i*a1)*a1=arrayi;else if(a

26、rrayi*b1)*b1=arrayi;amaxaminamax_pamin_p12-23 5 78 27 6 9 36 3 41212max_min_value(number,10,amax_p,amin_p);array10na1b1三、指向多维数组的指针和指针变量三、指向多维数组的指针和指针变量int a34=6,9,0,16,8,-1,2,7,3,48,-5,12;(1)a+i=ai=*(a+i)a=a0=*(a+0)=*a=&a00aa+0a+1a+2a0a1a2(2)ai+j是是aij的地址的地址 *(a+i)+j也是也是aij的地址的地址(3)&ai或或a+i指向指向行行,*(a

27、+i)或或ai指向指向列列(4)aij的的值值可以表示为:可以表示为:*(ai+j)*(*(a+i)+j)aij690168-127348-5121多维数组的地址多维数组的地址对于一维数组对于一维数组ai=*(a+i)=*(p+i)=pi#define FORMAT%d,%dnvoid main()static int a34=1,3,5,7,9,11,13,15,17,19,21,23;printf(FORMAT,a,*a);printf(FORMAT,a0,*(a+0);printf(FORMAT,&a0,&a00);printf(FORMAT,a1,a+1);printf(FORMAT,

28、&a10,*(a+1)+0);printf(FORMAT,a2,*(a+2);printf(FORMAT,&a2,a+2);printf(FORMAT,a10,*(*(a+1)+0);运行结果:运行结果:158,158158,158158,158166,166166,166174,174174,1749,9 2多维数组的指针多维数组的指针可以用指针变量指向多维数组及其元素可以用指针变量指向多维数组及其元素(1)指向数组元素的指针变量。指向数组元素的指针变量。例例5:用指针变量输出数组元素的值。:用指针变量输出数组元素的值。void main()static int a23=2,3,6,7,8,

29、5;int i,j,*p;p=&a00;/*p=a0;或或 p=*a;*/for(i=0;i2;i+)for(j=0;j3;j+,p+)printf(%3d,*p);printf(n);2 3 6 7 8 5aa0a1p23 2 3 6pp6p7p8p5p例例6:用指针变量输出数组元素:用指针变量输出数组元素aij的值。的值。void main()static int a23=2,3,6,7,8,5;int i,j,*p;p=a;scanf(%d%d,&i,&j);printf(%3d,*(p+i*3)+j);void main()static int a45=1,4,2,3,7,6,9,10

30、,8,-1,-2,-6,-4,4,2,7,6,9,11,14;int i,j;for(i=0;i4;i+)for(j=0;j5;j+)printf(%4d,aij);printf(n);sort(a,4*5);printf(=n);for(i=0;i4;i+)for(j=0;j5;j+)printf(%4d,aij);printf(n);例例7:7:将一个二维数组将一个二维数组a45a45进行按行全排序进行按行全排序 void sort(int*p,int n)int i,j,t;for(i=0;in-1;i+)for(j=i+1;j=n-1;j+)if(*(p+i)*(p+j)t=*(p+i

31、);*(p+i)=*(p+j);*(p+j)=t;a00a01a02a03a04a10a11a12a13a14 .a32a33a34.sort(a,4*5);p(2)指向由指向由m个整数组成的一维数组的指针变量。个整数组成的一维数组的指针变量。例例7:输出二维数组任一行任一列的元素的值。:输出二维数组任一行任一列的元素的值。void main()static int a34=1,3,5,7,9,11,13,15,17,19,21,23;int(*p)4,i,j;p=a;scanf(i=%d,j=%d,&i,&j);printf(a%d,%d=%dn,i,j,*(*(p+i)+j);说明说明:(

32、1)int(*p)4 表示表示p指向指向一个包含一个包含4个元素的个元素的一维数组一维数组.(2)p+1使指针移动使指针移动2*4个字节个字节,*(p+1)使指针的指向由横使指针的指向由横 向转向纵向向转向纵向.(3)*(p+i)+j使指针移动使指针移动2*4*i+2*j.(3)多维数组的指针作函数参数。多维数组的指针作函数参数。例例9:9:求二维数组求二维数组a45a45每列最大值每列最大值 void colum_max(a,b)int(*a)5,*b;int i,j;for(j=0;j5;j+)for(i=1;i4;i+)if(*(b+j)*(*(a+i)+j)*(b+j)=*(*(a+i

33、)+j);int a45,b5;colum_max(a,b);a+0a+1a+2a+3b 2 12 3 27 -4 3 7 33 2 5 1 6 12 3 15 4 8 10 9 14 2 12 3 27 -4.3 4123327515 void main()int a45,b5;int i,j;for(i=0;i4;i+)for(j=0;j5;j+)scanf(%d,&aij);bj=a0j;colum_max(a,b);for(i=0;i4;i+)for(j=0;j5;j+)printf(%4d,aij);printf(n);printf(=n);for(j=0;j5;j+)printf(

34、%4d,bj);printf(n);打印原二维数组打印原二维数组打印每列最大值打印每列最大值 例例8:有一个班,:有一个班,30个学生,各学个学生,各学4门课,计算总平均分门课,计算总平均分 以及第以及第n个学生的成绩。个学生的成绩。void average(float*p,int n)float*p_end;float sum=0,aver;p_end=p+n;for(;pp_end;p+)sum=sum+(*p);aver=sum/n;printf(%5.2fn,aver);void search(float(*p)4,int n)int i;for(i=0;i4;i+)printf(%5

35、.2f,*(*(p+n)+i);void main()int i,j,score304;for(i=0;i30;i+)for(j=0;j4;j+)scanf(%d,&scoreij);average(*score,12);scanf(%d,&n);search(score,n);例:上题基础上,查找有一门以上课程不及格的学生,打例:上题基础上,查找有一门以上课程不及格的学生,打出它们的全部课程的成绩。出它们的全部课程的成绩。void search(float(*p)4,int n)int i,j,flag;for(i=0;i4;i+)if(*(*(p+j)+i)60)flag=1;if(flag=1)printf(NO.%d is fails,his score are:n,j+1);for(i=0;i,4;i+)printf(%5.1f,*(*(p+j)+i);printf(n);void main()void average();void search();static float score34=65,57,70,60,58,87,90,81,90,99,100,98;search(score,3);

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!