1第8章指针C语言程序设计北京科技大学计算机系2020/1/1128.1指针和指针变量8.2指针与数组8.3指针与函数第8章指针2020/1/1138.1指针和指针变量main(){floatx;inty;…}8.1.1指针和指针变量的概念变量的两个物理意义200020012002200320042005…xy变量的内容变量的地址2020/1/1148.1指针和指针变量main(){inta,b,c;a=5;b=3;c=a+b;…}8.1.1指针和指针变量的概念200020012002200320042005abc5直接将整数5存入变量a3直接将整数3存入变量b8直接将变量a、b的值取出,相加后存入变量c利用变量名存取数据的方式称为“直接存取”方式。2020/1/115C语言还提供了对内存单元的“间接存取”方式p20002001200220032004200520062007abc532004a和b相加的结果(*p=a+b)存放到变量p所指向的内存单元中去。此时c称为指针变量p的目标变量。p2004cp=&c8main(){inta=5,b=3,c,*p;p=&c;*p=a+b;…}8.1指针和指针变量8.1.1指针和指针变量的概念●变量的地址称为变量的指针●存放地址的变量称为指针变量2020/1/116main(){inta,*p=&a;floatx,*q=&x;…}2000200120022003200420052006200720082009apxq20048.1指针和指针变量8.1.2指针变量的定义2000main(){inta,*p;floatx,*q;p=&a;q=&x;…}指针变量定义的形式指针变量初始化2020/1/117main(){inta,*p=&a;floatx,*q=&x;*p=5;printf(a+3=%d\n,*p+3);…}间接存取运算2000200120022003200420052006200720082009apxq20048.1指针和指针变量8.1.3指针的基本运算2000*p=&a;×main(){inta,*p;floatx,*q;p=&a;q=&x;…}赋值运算52020/1/118方法1:目标变量值不变,改变指针变量的指向求解。main(){inta,b,*p1,*p2,*p;p1=&a;p2=&b;scanf(″%d%d″,p1,p2);if(*p1*p2){p=p1;p1=p2;p2=p;}printf(″a=%d,b=%d\n″,a,b);printf(″max=%d,min=%d\n″,*p1,*p2);}abp1p2p68a=6,b=8max=8,min=68.1指针和指针变量【例8.1】输入a、b两个整数,使用指针变量按大小顺序输出这两个整数。2020/1/119方法2:利用指针变量直接改变目标变量的值求解。main(){inta,b,t,*p1,*p2;p1=&a;p2=&b;scanf(″%d%d″,p1,p2);if(*p1*p2){t=*p1;*p1=*p2;*p2=t;}printf(″a=%d,b=%d\n″,a,b);printf(″max=%d,min=%d\n″,*p1,*p2);}a、*p1b、*p2p1p2t68a=8,b=6max=8,min=68.1指针和指针变量6862020/1/1110指针的加减运算8.1指针和指针变量8.1.3指针的基本运算main(){inta[]={10,20,30,40,50},*p1,*p2;p1=p2=a;printf(″p1=%u,*p1=%d\n″,p1,*p1);p2+=3;printf(″p2=%u,*p2=%d\n″,p2,*p2);}P1=404,*p1=10P2=410,*p2=40404405406407408409410411412413a[0]a[1]a[2]a[3]a[4]3020104050p1p2指针加减运算要点:①只有当指针变量指向数组时指针的加减运算才有意义。②指针变量可加减一个整型表达式。如:p1++、p2+3、p2--、p2-2。③指针的加减运算是以基类型为单位(即sizeof(类型))的。④两个指针变量不能作加法运算,只有当两个指针变量指向同一数组时,进行指针变量相减才有实际意义。如:p2-p1。2020/1/1111指针的关系运算8.1指针和指针变量8.1.3指针的基本运算404405406407408409410411412413a[0]a[1]a[2]a[3]a[4]3020104050p1p2①指向同一数组的两个指针可以进行关系运算,表明它们所指向元素的相互位置关系。如:p2p1、p2==p1。②指针与一个整型数据进行比较是没有意义的。③不同类型指针变量之间比较是非法的。④NULL可以与任何类型指针进行==、!=的关系运算,用于判断指针是否为空指针。2020/1/1112⑴数组名是该数组的指针a是数组的首地址(即a[0]的地址),是一个指针常量。a=&a[0],a+1=&a[1],…,a+9=&a[9]数组元素的下标表示法:a[0],a[1],…,a[i],…,a[9]数组元素的指针表示法:*(a+0),*(a+1),…,*(a+i),…,*(a+9)8.2指针与数组8.2.1指向数组的指针1.一维数组的指针例如:inta[10],*p;a[0]a[9]pa2020/1/1113当p指向a[0]时,用p表示数组元素下标法:p[0],p[1],…,p[i],…,p[9]指针法:*(p+0),*(p+1),…,*(p+i),…,*(p+9)a[0]a[9]p8.2指针与数组8.2.1指向数组的指针1.一维数组的指针⑵指向一维数组元素的指针变量由于数组元素也是一个内存变量,所以此类指针变量的定义和使用与指向变量的指针变量相同。例如:inta[10],*p;p=a;(或p=&a[0];)a2020/1/1114a[0]a[9]pa【例8.3】用指针法输出数组元素。main(){inta[10],i,*p;for(i=0;i10;i++)scanf(%d,a+i);for(i=0;i10;i++)printf(%4d,*(a+i));printf(\n);for(p=a,i=0;i10;i++)printf(%4d,*(p+i));printf(\n);}8.2指针与数组8.2.1指向数组的指针1.一维数组的指针1234567891012345678910123456789102020/1/1115a[0]a[9]pa【例8.3】用指针法输出数组元素。main(){inta[10],i,*p;for(p=a;pa+10;p++)scanf(%d,p);for(p=a;pa+10;p++)printf(%d,*p);printf(\n);}8.2指针与数组8.2.1指向数组的指针1.一维数组的指针123456789102020/1/1116a[0]a[9]pa[1]......12345678910a数组名是地址,指向数组的指针变量存放的也是地址。通过指针变量也可以引用数组元素。p=&a[0]等效于p=a。数组名和指向数组的指针变量的区别:指针变量p是变量可以赋值,数组名a是地址常量不能赋值。8.2指针与数组8.2.1指向数组的指针用指针变量引用数组元素,必须关注其当前值。例如:p=p+3*(p-1)、p[-1]等价于a[2]2020/1/1117【例8.4】输入五个整数,使用指针变量将这五个数按从小到大排序后输出。main(){inta[5],*pp,*p,*q,t;for(p=a;pa+5;p++)scanf(%d,p);for(p=a;pa+4;p++){pp=p;for(q=p+1;qa+5;q++)if(*pp*q)pp=q;if(pp!=p){t=*p;*p=*pp;*pp=t;}}for(p=a;pa+5;p++)printf(%d,*p);printf(\n);}8.2指针与数组输入a数组for(p=a;pa+4;p++)pp=pfor(q=p+1;qa+5;q++)T*pp*qFpp=qTpp!=pF*pp*p输出a数组图8.9选择法排序N-S图2020/1/111801020111212122231323a⑴二维数组的地址例如:inta[3][4];①二维数组名a是数组的首地址。②二维数组a包含三个行元素:a[0]、a[1]、a[2]。a[0]a[1]a[2]a三个行元素的地址分别是:a、a+1、a+2。而a[0]、a[1]、a[2]也是地址量,是一维数组名,即*(a+0)、*(a+1)、*(a+2)是一维数组首个元素地址。8.2指针与数组8.2.1指向数组的指针2.二维数组的指针a+1a+22020/1/1119⑵二维数组元素的地址a[0]、a[1]、a[2]是一维数组名,所以a[i]+j是数组元素的地址。数组元素a[i][j]的地址可以表示为下列形式:&a[i][j]、a[i]+j、*(a+i)+j01020111212122231323a[0]数组a[1]数组a[2]数组8.2指针与数组8.2.1指向数组的指针2.二维数组的指针a[2]+1a[2]+2a[2]+3a[0]+1a[0]+2a[0]+32020/1/1120⑶二维数组元素的表示法数组元素可用下列形式表示:a[i][j]、*(a[i]+j)、*(*(a+i)+j)8.2指针与数组8.2.1指向数组的指针2.二维数组的指针a是二维数组,根据C的地址计算方法,a经过两次*操作才能访问到数组元素。所以*a是a[0],**a才是a[0][0]。a[0]是a[0][0]的地址,*a[0]是a[0][0]。01020111212122231323a[0]a[1]a[2]a2020/1/1121⑷指向二维数组元素的指针变量8.2指针与数组8.2.1指向数组的指针2.二维数组的指针【例8.5】用指向数组元素的指针变量输出数组元素。main(){inta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}},i,j,*p;for(p=a[0],i=0;i3;i++){for(j=0;j4;j++)printf(%4d,*(p+i*4+j));/*元素的相对位置为i*4+j*/printf(\n);}}这种指针变量的定义及使用与指向一维数组元素的指针变量是相同的,用它存放二维数组元素的地址。01020111212122231323ap2020/1/1122⑸指向一维数组的指针变量指向一维数组指针变量的定义形式:数据类型标识符(*变量名)[元素个数]8.2指针与数组8.2.1指向数组的指针2.二维数组的指针“*”表示其后的变量名为指针类型,[元素个数]表示目标变量是一维数组,并说明一维数组元素的个数。由于“*”比“[]”的运算级别低,“*变量名”作为一个说明部分,两边必须加括号。“数据类型标识符”是定义一维数组元素的类型。2020/1/1123【例8.6】用指向一维数组的指针变量输出数组元素。main(){inta[3][4]={{0,1,2,3},{10,11,12,13},{20,21,22,23}};int(*lp)[4],i,j;for(lp=a,i=0;i3;i++){for(j=0;j4;j++)printf(%4d,*(*(lp+i)+j));printf(\n);}}8.2指针与数组8.2.1指向数组的指针2.二维数组的指针01020111212122231323alplp+1lp+2012310111213202122232020/1/1124【例8.6】用指向一维数组的指针变量输出数组元素。main(){inta[][4]={0,1,2,3,10,11,12,13,20,21,22,23};int(*lp)[4],j;for(lp=a;lpa+3;lp++){for(j=0;j4;j++)pr