《c程序设计 第10章 指针.ppt》由会员分享,可在线阅读,更多相关《c程序设计 第10章 指针.ppt(65页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第1010章章 指指 针针主要内容:主要内容:变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量 字符串指针和指向字符串指针变量字符串指针和指向字符串指针变量使用指针的优点:使用指针的优点:1、能有效地表示复杂的数据结构、能有效地表示复杂的数据结构2、能动态分配内存、能动态分配内存3、能方便地使用字符串和数组、能方便地使用字符串和数组4、在函数调用时能获得一个以上的值、在函数调用时能获得一个以上的值5、能直接处理内存地址、能直接处理内存地址地址地址-内存内存字节字节编号编号内存单元内存单元-存放数据的基本单位存放数据的基
2、本单位变量名变量名-标识内存单元标识内存单元指针指针-变量地址变量地址(变量所占内存单元首字节变量所占内存单元首字节地址地址)指针变量指针变量-存放变量地址存放变量地址10.1 指针的概念指针的概念C程序对变量值的存取方式程序对变量值的存取方式1、“直接访问直接访问”方式:方式:按变量名与内存地址的对应关系按变量名与内存地址的对应关系 直接按变量地址存取。直接按变量地址存取。2、“间接访问间接访问”方式:方式:通过指向变量的指针,对其指向通过指向变量的指针,对其指向 的变量值进行间接存取。的变量值进行间接存取。10.1 地址和指针的概念地址和指针的概念在在编译编译时时就给这个就给这个变量分配变
3、量分配内存单元内存单元图图10.210.2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量变量的指针就是变量的地址。存放变量变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一地址的变量是指针变量,用来指向另一个变量。个变量。图图10.310.3一、指针变量的定义一、指针变量的定义类型符类型符 *指针变量名;指针变量名;例:例:float *p1,*p2;int *p3,*p4;二、指针变量的引用二、指针变量的引用1、相关的运算、相关的运算&取地址运算符取地址运算符 *指针运算符指针运算符例:例:&a(a 变量变量的地址)的地址)*p(指针变量指针变量p所指向的变
4、量)所指向的变量)p=&a;pointer_1=&i;*pointer_1的值为的值为i的值的值pointer_2=&j;*pointer_2的值为的值为j的值的值在定义指针变量时在定义指针变量时要注意要注意:(1)指针变量前面的指针变量前面的“*”,表示该变量的,表示该变量的类型为指针型变量。类型为指针型变量。(2)在定义指针变量时必须指定基类型。在定义指针变量时必须指定基类型。(3)(3)只能取已经分配了内存变量的地址赋给只能取已经分配了内存变量的地址赋给指针变量指针变量(4)指针使用前必须有合法的地址值。指针使用前必须有合法的地址值。int *p;*p=20;例例10.1 通过指针变量访
5、问整型变量。通过指针变量访问整型变量。main()int a,B;int*pointer-1,*pointer-2;a=100;B=10;pointer-1=&a;/*把变量把变量a的地址赋给的地址赋给pointer-1*/pointer-2=&B;/*把变量把变量B的地址赋给的地址赋给pointer-2*/printf(%D,%Dn,a,B);printf(%D,%Dn,*pointer-1,*pointer-2);图图10.5图图10.610.6例例10.2 整数,按先大后小的顺序输出整数,按先大后小的顺序输出a和和B。main()int*p1,*p2,*p,a,B;scanf(%D,%D
6、,&a,&B);p1=&a;p2=&B;if(aB)p=p1;p1=p2;p2=p;/*同同类型指针类型指针*/printf(na=%D,B=%Dnn,a,B);printf(max=%D,min=%Dn,*p1,*p2);2、指针与算术运算、指针与算术运算pxpx+n +n 等价于等价于(p)+n*p)+n*sizeofsizeof(数据类型数据类型)pxpx-n -n 等价于等价于(p)-n*p)-n*sizeofsizeof(数据类型数据类型)&、*与与+、-运算同级运算同级同级运算同级运算从右到左从右到左 例:例:*p+等价于等价于*(p+),即即*p,p+;若:若:p=&a;则:则:
7、(*p)+等价于等价于 a+&*p 等价于等价于&a *&a 等价于等价于 a10.2.3 指针变量作为函数参数指针变量作为函数参数 共享内存共享内存,“双向双向”传递传递swap(int*p1,int*p2)int temp;temp=*p1;*p1=*p2;*p2=temp;main()int a,B;int*pointer-1,*pointer-2;scanf(%D,%D,&a,&B);pointer-1=&a;pointer-2=&B;if(aB)swap(pointer-1,pointer-2);printf(n%D,%Dn,a,B);如果想通过函数调用得到如果想通过函数调用得到n个
8、要改变的值:个要改变的值:在主调函数中设在主调函数中设n个变量,用个变量,用n个指针变个指针变量指向它们量指向它们;然后将指针变量作实参,将这然后将指针变量作实参,将这n个变量个变量的地址传给所调用的函数的形参的地址传给所调用的函数的形参;通过形参指针变量,改变该通过形参指针变量,改变该n个变量值个变量值;主调函数中就可以使用这些改变了值主调函数中就可以使用这些改变了值的变量。的变量。#include void function(int a,int b,int*c,int*d)*c=a+b;*d=2*a+b;main()int x,y,z,t;scanf(%d,%d,&x,&y);functi
9、on(x,y,&z,&t);printf(z=%d t=%dn,z,t);主子程序主子程序之间数据传递的方式之间数据传递的方式:1.实参实参-形参的值传递;形参的值传递;return语语句。句。2.全局变量。全局变量。3.形参为指针。形参为指针。4.函数参数函数参数(形参或实参形参或实参)为数组名或为数组名或指针。指针。10.3 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量 指针变量可以指向数组和数组元素指针变量可以指向数组和数组元素(把数把数组起始地址或某一元素的地址放到一个组起始地址或某一元素的地址放到一个指针变量中指针变量中)。所谓所谓数组的指针数组的指针是指数组的起始地
10、址,是指数组的起始地址,数组元素的指针是数组元素的地址。数组元素的指针是数组元素的地址。引用数组元素可以用下标法引用数组元素可以用下标法(如如a3),也也可以用指针法,即通过指向数组元素的可以用指针法,即通过指向数组元素的指针找到所需的元素。指针找到所需的元素。数组的指针:数组的指针:int*p,a10;p=a;数组首地址数组首地址 数组第一个元素的地址(指针)数组第一个元素的地址(指针)注意注意:数组名代表数组首地址(是常量)数组名代表数组首地址(是常量)数组元素的指针:数组元素的指针:p=&a1;数组元素的地址(首字节地址)数组元素的地址(首字节地址)10.3.1 指向数组元素的指针指向数
11、组元素的指针定义一个指向数组元素的指针变量的方法,定义一个指向数组元素的指针变量的方法,与以前介绍的指向变量的指针变量相同。与以前介绍的指向变量的指针变量相同。int a10;int*p;/*p指向整型变量的指针变指向整型变量的指针变量量*/赋值赋值将数组元素的地址赋给指针变量将数组元素的地址赋给指针变量(1)利用赋值语句)利用赋值语句 p=&a5;(2)定义指针变量时赋初值定义指针变量时赋初值 例:例:int a10,*p=&a0;或或*p=a;图图10.1210.3.2 通过指针引用数组元素通过指针引用数组元素表示表示ai的形式:的形式:ai*(a+i)*(p+i)pi如果如果p=&a4;
12、p2=?如果如果p的初值为的初值为&a0,则:则:(1)p+i和和a+i就是就是ai的地址的地址。可以可以p=p+i;不有不有a=a+i?也不能也不能a+;(2)*(p+i)或或*(a+i)是是p+i或或a+i所指向的所指向的数组元素,即数组元素,即ai。例如,例如,*(p+5)或或(a+5)就是就是a5。即即*(p+5)=*(a+5)=a5。(3)指向数组的指针变量也可以带下标,指向数组的指针变量也可以带下标,如如pi与与(p+i)等价。等价。指针变量的关系运算指针变量的关系运算若若p1和和p2指向同一数组,则指向同一数组,则vp1p2 表示表示p1指的元素在后指的元素在后vp1=p2 表示
13、表示p1与与p2指向同一指向同一元素元素若若p1与与p2不指向同一数组,比较不指向同一数组,比较无意义无意义p=NULL或或p!=NULL#include void main()int a10=2,3,4,5,6,1,7,8,9,10,*p,i;p=a;/*p=&a0;*/scanf(%d,&i);if(i=0&ip。*(p+)与与*(+p)作用不同作用不同(*p)+表示表示p所指向的元素值加所指向的元素值加1 p当前指向当前指向a中第中第i个元素,则:个元素,则:*(p-)相当相当ai-,对对p进行进行“*”运算,运算,p自自减。减。(+p)相当相当a+i,先使先使p自加,再作自加,再作*运
14、算。运算。(-p)相当于相当于a-i,先使先使p自减,再作自减,再作*运算。运算。main()int a5=1,2,3,4,5,i=0;printf(n%d%d,ai+,a+i);printf(n%d%d,a-i,ai-);/*2 2 回车回车 2 3*/10.3.3 用数组名作函数参数用数组名作函数参数数组名可以用作函数的形参和实参。数组名可以用作函数的形参和实参。f(int arr,int n)和和f(int*arr,int n)是是等价。等价。调用时可以是指向数组的指针或数组名调用时可以是指向数组的指针或数组名.例例10.7 将数组将数组a中中n个整数按相反顺序存放个整数按相反顺序存放v
15、oid inv(int x,int n)/*形参形参x是数组名是数组名*/int temp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;return;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(%D,,ai);printf(n);inv(a,10);printf(The array haS Been inverteD:n);for(i=0;i10;i+)printf(%D,,ai);prin
16、tf(n);程序如下:程序如下:void inv(int *x,int n)/*形参形参x为指针变量为指针变量*/intp,temp,*i,*j,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;return;main()int i,a10=3,7,9,111,0,6,7,5,4,2;printf(The oriGinal array:n);for(i=0;i10;i+)printf(%D,ai);printf(n);inv(a,10);printf(The array haS Been inverteD:n);f
17、or(i=0;i10;i+)printf(%D,ai);printf(n);例例:从从10个数中找出其中最大值和最小值。个数中找出其中最大值和最小值。int max,min;/*全局变量全局变量*/void max-min-value(int array,int n)intp,*array-enD;array-enD=array+n;max=min=*array;/*max=min=array0;*/for(p=array+1;parray-enD;p+)if(*pmax)max=*p;else if(*pmin)min=*p;return;main()int i,numBer10;print
18、f(enter 10 inteGer numBerS:n);for(i=0;i10;i+)scanf(%D,&numBeri);max-min-value(numBer,10);printf(nmax=%D,min=%Dn,max,min);图图10.18实参不用数组名,而用指针变量传递地址,实参不用数组名,而用指针变量传递地址,形参仍用指针变量。形参仍用指针变量。int max,min;void max-min-value(int*array,int n)intp,*array-end;array-end=array+n;max=min=*array;for(p=array+1;parray
19、-enD;p+)if(*pmax)max=*p;else if(*pmin)min=*p;return;main()int i,number10,*p;p=numBer;/*使使p指向指向number数组数组*/printf(enter 10 integer numbers:n);for(i=0;i10;i+,p+)scanf(%d,p);printf(the 10integer numbers:n);for(p=number,i=0;i10;i+,p+)printf(%d,*p);p=number;max-min-value(p,10);/*实参用指针变量实参用指针变量*/printf(nm
20、ax=%d,min=%dn,max,min);例 void main()int a=5,8,7,6,2,7,3;int y,*p=&a1;y=(*-p)+;printf(“%d ”,y);printf(“%d”,a0);输出:5 6例例 注意指针变量的运算注意指针变量的运算如果实参数组想在函数中改变此数组的元如果实参数组想在函数中改变此数组的元素的值,素的值,实参与形参表示形式有以下情况:实参与形参表示形式有以下情况:(1)形参和实参都用数组名形参和实参都用数组名 f(int x,int n)调用调用 f(a,10);/*a是数组是数组*/(2)实参用数组名,形参用指针变量。实参用数组名,形参
21、用指针变量。f(int*x,int n)调用调用f(a,10);/*a是数组名是数组名*/(3)实参形参都用指针变量。实参形参都用指针变量。f(int*x,int n);p=a;f(p,10);(4)实参为指针变量,形参为数组名。实参为指针变量,形参为数组名。f(int x,int n);p=a;f(p,10);数组名作函数参数数组名作函数参数数组名作函数参数,是数组名作函数参数,是地址传递地址传递数组名作函数参数,实参与形参的对数组名作函数参数,实参与形参的对应关系应关系实参形参数组名指针变量数组名指针变量数组名数组名指针变量指针变量10.3 指向多维数组的指针和指针变量指向多维数组的指针和
22、指针变量1、二维数组的地址、二维数组的地址设数组定义为:设数组定义为:a34a0 a00,a01,a02,a03 a1 a10,a11,a12,a13 a2 a20,a21,a22,a23 视视 ai 为一维数为一维数组名,组名,aij 为为 ai 数组元素数组元素视视 a为一维数为一维数组名,组名,ai 为为 a 数组元素数组元素二维数组元素表示形式:二维数组元素表示形式:(1)a12(2)*(a1+2)(3)*(*(a+1)+2)(4)*(&a00+1*4+2)地址表示:地址表示:(1)&a12(2)a1+2(3)*(a+1)+2(4)&a00+1*4+2地址地址:a 数组首地址,即数组首
23、地址,即 a00 的地址的地址 a+0=a0第第0行首地址行首地址=数组首地址数组首地址 a+i=ai第第i行首地址行首地址=ai0的地址的地址 ai+j=*(a+i)+jaij的地址的地址(1)指向数组元素的指针变量)指向数组元素的指针变量设二维数组设二维数组 anm 若指针变量若指针变量 p=&a00或或p=a0或或p=*a则则指向指向 aij 的指针为的指针为 p+i*m+j即:即:*(p+i*m+j)=aij(2)指向一维数组的指针变量的定义指向一维数组的指针变量的定义类型符类型符 (*指针变量名)指针变量名)m指向一维数组指针变量与数组元素的对应指向一维数组指针变量与数组元素的对应若
24、若 p=a,则则*(p+i)+j 指向指向 aij从而有:从而有:*(*(p+i)+j)=aij#include void main()static int a35=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;int i,j,(*p)5,*pa;scanf(%d%d,&i,&j);printf(naij =%d,aij);printf(n*(ai+j)=%d,*(ai+j);printf(n*(*(a+i)+j)=%d,*(*(a+i)+j);p=a;/not p=a0 not p=&a00 printf(npij =%d,pij);printf(n*(pi+j)=
25、%d,*(pi+j);printf(n*(*(p+i)+j)=%d,*(*(p+i)+j);pa=a0;/or pa=&a00 not pa=a printf(n%dn,*(pa+5*i+j);for(;paa0+15;pa+)printf(%6d,*pa);3、多维数组的指针作函数参数、多维数组的指针作函数参数形参形参用指向数组元素的指针变量用指向数组元素的指针变量用指向一维数组的指针变量用指向一维数组的指针变量例例10.4 (习题习题8.14 p186 、)分析:分析:1)全局数组)全局数组 a10,b5 存放每个学生的平均存放每个学生的平均 分数和每门课程的平均分数。分数和每门课程的平均
26、分数。2)函数)函数aver1和和aver2分别求上述平均分。分别求上述平均分。float a10,b5;/*全局全局数组数组*/void aver1(float(*p)5,int n,int m)float s;int i,j;for(i=0;in;i+)s=0;for(j=0;jm;j+)s=s+*(*(p+i)+j);ai=s/m;void aver2(float*p,int n,int m)/*指指针针*/float s;int i,j;for(j=0;jm;j+)s=0;for(i=0;in;i+)s=s+*(p+i*m+j);bj=s/n;main()static float sc
27、ore105=;int i,j;aver1(score,10,5);aver2(*score,10,5);for(i=0;i10;i+)for(j=0;j5;j+)printf(“%8.1f”,scoreij);printf(“%10.2fn”,ai);for(j=0;j5;j+)printf(“%8.1f”,bj);若int a34;int (*p1)4=a;int *p2=a0;实参形参数组名int x4指针变量int (*q)4数组名int x4指针变量int(*q)4数组名a数组名a指针变量p1指针变量p1指针变量p2指针变量int *q10.4 字符串的指针和指向字符串的指针变量1、
28、用字符数组表示、用字符数组表示例:例:static char s=“Happy New Year!”;因数组名因数组名 s 代表数组首地址,代表数组首地址,则则*(s+i)=si2、用字符指针表示、用字符指针表示例:例:char*s=“Happy New Year!”;等价于:等价于:char *s;s=“Happy New Year!”;注意:注意:1、s 不是指针变量不是指针变量 2、s 的使用方法同字符数组名的使用方法同字符数组名例例10.18 将字符串将字符串a复制为字符串复制为字符串b。main()char a=i am a boy.,b20;int i;for(i=0;*(a+i)
29、!=0;i+)*(b+i)=*(a+i);*(b+i)=0;printf(string a is:%sn,a);printf(string b is:);for(i=0;bi!=0;i+)printf(%c,bi);printf(n);例例10.19用指针变量来处理例用指针变量来处理例10.18问题。问题。main()char a=I am a Boy.,B20,*p1,*p2;int i;p1=a;p2=B;for(;*p1!=0;p1+,p2+)*p2=*p1;*p2=0;printf(string a is:%Sn,a);printf(string B is:);for(i=0;Bi!=
30、0;i+)printf(%C,Bi);printf(n);10.4.2 字符串指针作函数参数字符串指针作函数参数将一个字符串从一个函数传递到另一个函将一个字符串从一个函数传递到另一个函数,可以用地址传递的办法,即用字符数,可以用地址传递的办法,即用字符数组名作参数或用指向字符串的指针变数组名作参数或用指向字符串的指针变量作参数。在被调用的函数中可以改变量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到字符串的内容,在主调函数中可以得到改变了的字符串。改变了的字符串。例例10.20用函数调用实现字符串的复制。用函数调用实现字符串的复制。(1)用字符数组作参数。用字符数组作参数。
31、void copy-string(char from,char to)int i=0;while(fromi!=0)toi=fromi;i+;toi=0;main()char a=I am a teacher.;char B=you are a student.;printf(string a=%snstring b=%sn,a,b);copy-string(a,b);printf(nstring a=%Snstring b=%sn,a,b);可以不定义字符数组,而用字符型指针变可以不定义字符数组,而用字符型指针变量。量。main函数可改写如下:函数可改写如下:main()char*a=I a
32、m a teacher.;char*b=you are a student.;printf(string a=%snstring b=%sn“,a,b);Copy-string(a,b);printf(na=%sn b=%sn,a,b);(2)形参用字符指针变量。程序如下:形参用字符指针变量。程序如下:void copy-string(char*from,char*to)for(;*from!=0;from+,to+)*to=from;*to=0;main()char*a=I am a teacher.;char*b=you are a student.;printf(n a=%Sn b=%S
33、n,a,b);copy-string(a,b);printf(n a=%Sn b=%sn,a,b);(3)对对Copy-string函数还可作简化。函数还可作简化。将将Copy-string函数改写为函数改写为void Copy-string(char*from,char*to)while(*to=*from)!=0)to+;from+;Copy-string函数的函数体还可改为函数的函数体还可改为 while(*to+=*from+)!=0);函数体还可写成函数体还可写成 while(*from!=0)*to+=*from+;to=0;while(*to+=*from+)!=0);函数体中函数体中while语句也可以改用语句也可以改用for语句:语句:for(;(*to+=*from+)!=0;);也可用指针变量,函数也可用指针变量,函数Copy-string写为写为:void Copy-string(char from,char to)charp1,*p2;p1=from;p2=to;while(*p2+=*p1+)!=0);第第258259页页 10.1、10.3、10.4、10.6、10.9、10.10、10.14
限制150内