《C语言第7章指针第1讲课件.ppt》由会员分享,可在线阅读,更多相关《C语言第7章指针第1讲课件.ppt(50页珍藏版)》请在三一办公上搜索。
1、第7章 指针(一),C语言程序设计,内容提要,指针概述指针的概念为什么引入指针的概念指针变量作为函数参数字符指针作为函数参数指针和数组间的关系一维数组的地址和指针二维数组的地址和指针,为什么引入指针的概念,铁杆C/C+程序员最挚爱的武器:指针C/C+的高效、高能主要来自于指针很多不可能的任务由指针完成,为什么引入指针的概念,指针为函数提供修改变量值的手段 为C的动态内存分配系统提供支持 为动态数据结构(如例链表、队列、二叉树等)提供支持 可以改善某些子程序的效率,内存的寻址方式,如何读写内存中的数据?通过变量的地址访问变量所在的存储单元两种寻址方式直接(寻址)访问通过变量地址直接存取变量内容间
2、接(寻址)访问通过指针变量来间接存取它所指向的变量i_pointer=,指针(Pointer)的概念,指针也是一种数据类型指针变量 声明为指针类型的变量,专门存放地址数据的变量,如何定义指针变量?,定义指针变量int*p;定义了一个指针变量p,简称指针pp是变量,int*是类型指针变量初始化int*p,a;p=*p 与 a 完全等价,int i,*p;p=,int*p;float*q;p=q;,int i;float*p;p=,int*p;p=100;,判断是真?是假?,指针变量只存放地址!,一个指针变量不能指向与其类型不同的变量!,我是真的,你猜对了吗?,应在类型相同的指针变量之间赋值,&与
3、*操作符,&用来取变量的地址*用来取指针指向的内存中的内容,int*p,a10;p=,int i=3,*p;p=,指针变量与其它类型变量的对比,共性在内存中占据一定大小的存储单元先定义,后使用特殊性 它的内容只能是地址,而不能是数据必须初始化后才能使用,否则指向不确定的存储单元,对该空间进行访问,将可能造成危险可参与的运算:加、减一个整数,自增、自减、关系、赋值只能指向同一基类型的变量,指针的指向,只能指向同一基类型的变量,否则将引起warningfloat x;int*p=TC编译warning:Suspicious pointer conversion in function mainVC
4、编译warning C4133:=:incompatible types-from float*to int*,指针运算,算术运算short*p,a10;p=a;p+;/*p的值增加多少?*/指针的加减运算是以其指向的类型的字节长度为单位的,6000600160026003600460056006,指针运算,int*p,*q,a10;p=a;q=指针运算不能乱算一般只进行指针和整数的加减运算,同类型指针之间的减法运算其它运算,比如乘法、除法、浮点运算、指针之间的加法等,并无意义,所以也不支持,指针运算,关系运算指向同一种数据类型的两个指针才能进行关系运算值为1或0p q p q p=q不能与非
5、指针类型变量进行比较,但可与NULL(即0值)进行等或不等的关系运算判断p是否为空指针P=NULLp!=NULL,指针运算,赋值运算指针在使用前一定要赋值为指针变量赋的值必须是一个地址,main()int*p;scanf(%d,p);,main()int a,*p=,错!但TC下不报错VC下报错,指针与函数,指针既然是数据类型,自然可以做函数参数和返回值的类型指针做函数参数的经典例子:两数的互换,void Swap(int*x,int*y)int temp;temp=*x;*x=*y;*y=temp;,main()int a,b;a=15;b=8;Swap(,void Swap(int x,i
6、nt y)int temp;temp=x;x=y;y=temp;,main()int a,b;a=15;b=8;Swap(a,b);printf(a=%d,b=%d,a,b);,程序 1,程序 2,例7.17.2:编写函数实现两数的互换,实 参,形 参,结果有何不同?,Not Work!Why?,主调函数,被调函数,main()int a,b;a=15;b=8;Swap(a,b);printf(a=%d,b=%d,a,b);,void Swap(int x,int y)int temp;temp=x;x=y;y=temp;,5,5,a,b,实 参,形 参,9,9,程序 1,x,y,5,5,te
7、mp,9,主调函数,被调函数,main()int a,b;a=15;b=8;Swap(,void Swap(int*x,int*y)int temp;temp=*x;*x=*y;*y=temp;,&a,&a,实 参,形 参,&b,&b,程序 2,x,y,5,temp,5,a,b,9,9,5,简单变量作函数参数与指针变量作函数参数的比较,swap函数的几种错误形式(1/3),参数单向传递void Swap(int x,int y)int temp;temp=x;/*x,y为内部变量*/x=y;y=temp;,swap函数的几种错误形式(2/3),参数单向传递void Swap(int*p1,in
8、t*p2)int*p;p=p1;/*p1,p2为内部变量*/p1=p2;p2=p;,swap函数的几种错误形式(3/3),指针p没有确切地址void Swap(int*p1,int*p2)int*p;/*指针p未初始化*/*p=*p1;*p1=*p2;*p2=*p;,字符串与字符数组、字符指针,C语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理字符串一串以0结尾的字符字符数组每个元素都是字符类型的数组char string100;字符指针指向字符类型的指针char*p;数组和指针可以等同看待,上面三者本质上是一回事,字符指针变量与字符数组的区别,定义方法不同 char
9、str10;char*ptr;赋值方法不同 char str10;str=”china”;/*错误*/strcpy(str,”china”);/*正确*/char*ptr;ptr=”china”;字符指针是变量,而数组名是地址常量,使用字符指针的注意事项,字符指针变量必须有明确的指向,否则使用是危险的例如,输入字符串时 char*a;scanf(%s,a);/*错误*/应为:char*a;char str10;a=str;scanf(%s,a);/*正确*/,例7.5:字符串拷贝用字符数组编程,void MyStrcpy(char dstStr,char srcStr)int i=0;whil
10、e(srcStri!=0)dstStri=srcStri;i+;dstStri=0;,void MyStrcpy(char*dstStr,const char*srcStr)while(*srcStr!=0)*dstStr=*srcStr;srcStr+;dstStr+;*dstStr=0;,当只允许函数访问地址内容,不允许修改时,可以把函数的指针参数定义为const,例7.5:字符串拷贝用字符指针编程,例7.5:字符串拷贝主函数程序,#include main()char a80,b80;printf(“Please enter a string:”);gets(a);MyStrcpy(b,
11、a);printf(“The copy is:”);puts(b);,例7.6:计算实际字符个数,unsigned int MyStrlen(char str)int i;unsigned int len=0;for(i=0;stri!=0;i+)len+;return(len);,unsigned int MyStrlen(char*pStr)unsigned int len=0;for(;*pStr!=0;pStr+)len+;return(len);,方法2:用字符指针实现,方法1:用字符数组实现,指针与数组,数组名就是一个指针只是不能修改这个指针的指向可以定义函数的参数为数组指针也可当
12、作数组名使用short*p,a10;p=a;数组元素的几种等价引用形式ai*(a+i)pi*(p+i),60006001600260036004600560066007,a,a+1,a+2,60006001600260036004600560066007,a,p+,p+,输入输出数组的全部元素,main()int a10;int i;for(i=0;i10;i+)scanf(%d,方法1:下标法,main()int a10;int*p,i;for(p=a;p(a+10);p+)scanf(%d,p);for(p=a;p(a+10);p+)printf(%d,*p);,方法2:指针法,例7.7:
13、插入排序,关键是:找到该插入的位置,然后依次移动插入位置及其后的所有元素腾出这一位置放入待插入的元素,例7.7:插入排序主函数,#include#define ARR_SIZE 10void Inseart(int a,int n,int x)main()/*教材268页*/int aARR_SIZE+1,x,i,n;Inseart(a,n,x);/*调用函数 实参a为数组名*/,例7.7:插入排序数组作形参,void Inseart(int a,int n,int x)int i,pos;for(i=0;(i ai);i+)pos=i;for(i=n-1;i=pos;i-)ai+1=ai;/
14、*向后移动*/apos=x;/*插入元素x到位置pos*/,main()/*教材270页*/int aARR_SIZE+1,x,i,n;Inseart(a,n,x);/*调用函数 实参a为数组名*/void Inseart(int*a,int n,int x)/*定义函数,形参a为指针变量*/,插入排序方式二,main()/*教材270页*/int aARR_SIZE+1,x,i,n;int*p=NULL;Inseart(p,n,x);/*调用函数 实参p指针变量*/void Inseart(int a,int n,int x)/*定义函数,形参a为数组*/,插入排序方式三,main()/*教
15、材270页*/int aARR_SIZE+1,x,i,n;int*p=NULL;Inseart(p,n,x);/*调用函数 实参p为指针变量*/void Inseart(int*a,int n,int x)/*定义函数,形参a为指针变量*/,插入排序方式4,例7.7:插入排序指针作形参,void Inseart(int*a,int n,int x)int i,pos;for(i=0;(i*(a+i);i+)pos=i;for(i=n-1;i=pos;i-)*(a+i+1)=*(a+i);/*向后移动*/*(a+pos)=x;/*插入元素x到位置pos*/,指针与二维数组,C语言将二维数组看作一
16、维数组,其每个数组元素又是一个一维数组按行顺序存放所有元素,aa0+0,a+1a1+0,a0+1,a0+2,&a00,&a10,&a11,a1+1,&a12,&a01,&a02,a1+2,int a23;,例7.8,任意输入英文的星期几,在查找星期表后输出其对应的数字。char weekDay710=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;,表7-1 星期表的内容,#include main()int i,pos;int findFlag=0;char x10;char weekDay10=Sunday,Monday,T
17、uesday,Wednesday,Thursday,Friday,Saturday;printf(Please enter a string:);scanf(%s,x);for(i=0;i 7,例7.8,指针与二维数组,a 代表二维数组的首地址,第0行的地址a+i 代表第i行的地址*(a+i)即 ai 代表第i行第0列的地址*(a+i)+j 即 ai+j 代表第i行第j列的地址*(*(a+i)+j)即 aij 代表第i行第j列的元素,行地址转变成列地址,指针与二维数组,二维数组的指针列指针int*p;p=*a;/用列地址初始化逐个元素查找元素所在位置相对于数组起始地址的偏移量i*n+jfor(
18、i=0;im;i+)for(j=0;jn;j+)printf(%d,*(p+i*n+j);,p,p+,指针与二维数组,二维数组的指针行指针int(*p)3,a43,*p1;p=a;/用行地址初始化p1=a0;/用元素地址初始化先逐行查找元素所在行再在行内逐列查找元素所在位置for(i=0;im;i+)for(j=0;jn;j+)printf(%d,*(*(p+i)+j);,p,p+,例7.3:在一个班级中找出最高分及其学号,void FindMax(float score,long num,int n,float pMaxScore,long pMaxNum)int i;pMaxScore=s
19、core0;pMaxNum=num0;for(i=1;i pMaxScore)pMaxScore=scorei;pMaxNum=numi;,能返回这两个值吗?,例7.3:在一个班级中找出最高分及其学号,void FindMax(float score,long num,int n,float*pMaxScore,long*pMaxNum)int i;*pMaxScore=score0;*pMaxNum=num0;for(i=1;i*pMaxScore)*pMaxScore=scorei;*pMaxNum=numi;,指针参数指定了存放这两个值的地址,例7.9:在多个班级中找出最高分及其所在班级
20、和学号,int FindMax(int pmn,int m,int n,int*pRow,int*pCol)int i,j,max;max=p00;*pRow=0;*pCol=0;for(i=0;i max)max=pij;*pRow=i;*pCol=j;return(max);,能这样传递m个班(每班n个学生)的成绩吗?,int FindMax(int*p,int m,int n,int*pRow,int*pCol)int i,j,max;max=p0;*pRow=0;*pCol=0;for(i=0;i max)max=pi*n+j;*pRow=i;*pCol=j;return(max);,指定存储m个班(每班n个学生)成绩的首地址,例7.9:在多个班级中找出最高分及其所在班级和学号,指针、数组以及其它的类型混合,基本数据类型int、long、char、short、float、double指针是一种数据类型是从其它类型派生的类型XX类型的指针数组也是一种数据类型是从其它类型派生的类型每个元素都有一个类型任何类型都可以做指针或者数组的基础类型它们自己也可以做彼此或自己的基础类型,