《指针和指针变量.ppt》由会员分享,可在线阅读,更多相关《指针和指针变量.ppt(61页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第七章第七章 指指 针针7.1 指针和指针变量指针和指针变量7.2 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量7.3 字符串的指针和指向字符串的指针变量字符串的指针和指向字符串的指针变量7.4 函数的指针和指向函数的指针变量函数的指针和指向函数的指针变量7.5 返回指针值的函数返回指针值的函数7.6 指针数组和指向指针的指针指针数组和指向指针的指针Return7.1 指针和指针变量指针和指针变量概念概念内存地址:内存中存储单元的编号计算机硬件系统的内存储器中,拥有大量的存储单元,为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”。每个存储单元都有一个惟一的
2、地址注意:内存单元的地址与内存单元中的数据是两个完全不同的概念变量地址;系统分配给变量的内存单元的起始地址变量值的存取通过变量在内存中的地址进行变量存取的方式:变量存取的方式:直接访问:直接访问:直接利用变量的地址进行存取如:scanf(“%d”,&num)间接访问:间接访问:通过另一变量访问该变量的值,即定义一种特殊的变量(称为指针变量),用来存放其它变量的地址593000300030024000变量i变量j变量i_pointer指针与指针变量指针与指针变量指针:即地址,一个变量的地址称为该变量的指针指针:即地址,一个变量的地址称为该变量的指针指针变量:专门用于存放其它变量地址的变量,指针指
3、针变量:专门用于存放其它变量地址的变量,指针变量的值是指针,即变量变量的值是指针,即变量num的地址的地址指针与指针变量的区别:即变量值与变量的区别指针与指针变量的区别:即变量值与变量的区别为表示指针变量和它指向的变量之间的关系,用指针为表示指针变量和它指向的变量之间的关系,用指针运算符运算符“*”表示表示 如:如:i=3;/*将将3直接赋给变量直接赋给变量i*/i_pointer=&i;/*使使i_pointer指向指向i*/*i_pointer=3;/*将将3赋赋给给指指针针变变量量i_pointer指指向向的的变变量量*/指针变量的定义指针变量的定义指针变量的定义的一般形式:指针变量的定
4、义的一般形式:数据类型数据类型 *标识符;标识符;如:如:int *p;char *str;标识符前面的标识符前面的*表示该变量为指针变量表示该变量为指针变量一个指针变量只能指向同一类型的变量,即只有同一类型一个指针变量只能指向同一类型的变量,即只有同一类型变量的地址才能放到指向该类变量的指针变量中变量的地址才能放到指向该类变量的指针变量中注意:注意:此时的指针变量p、str 并未指向某个具体的变量(称指针是悬空的)。使用悬空指针很容易破坏系统,导致系统瘫痪指针变量的引用指针变量的引用&:取地址运算符:取地址运算符*:指针运算符:指针运算符例例7.1.1指针变量的定义与引用指针变量的定义与引用
5、 main()int a,b;int *p1,*p2;/*定义指针变量定义指针变量*p1、*p2*/a=100;b=10;p1=&a;/*把变量把变量a的地址赋给的地址赋给p1*/p2=&b;/*把变量把变量b的地址赋给的地址赋给p2*/printf(“%d,%dn”,a,b);printf(“%d,%d n”,*p1,*p2);注:如果执行了注:如果执行了 “p1=&a;”语句,则语句,则&*p1与与&a相同相同 指针变量的运算指针变量的运算赋值运算赋值运算 int a=1,b,*p;p=&a;b=*p;算术运算算术运算+、-p+/+P、P-/-P (*p)+a+*(p+)加、减整型数据加、
6、减整型数据 pn:将指针从当前位置向前(+n)或回退(-n)n个数据单位,而不是n个字节指向同一数组的不同元素的指针之间的减法指向同一数组的不同元素的指针之间的减法p1-p2:两指针之间的数据个数指针变量的比较运算指针变量的比较运算:地址之间、位置的前后关系,前者为小,后者为大指针变量的下标运算指针变量的下标运算:pi *(p+i)p=1;1199abp例例7.1.2输入两个整数,按从大到小顺序输出输入两个整数,按从大到小顺序输出main()int a,b,*p1,*p2,*p;scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)/*如果如果ab,则交换指针则交换指针
7、*/p=p1;p1=p2;p2=p;printf(“a=%d,b=%dn”,a,b);printf(“max=%d,min=%dn”,*p1,*p2);运行情况如下:运行情况如下:5,9 a=5,b=9 max=9,min=5p&ap15a&bp29bp&bp15a&ap29b指针变量作函数参数指针变量作函数参数指针变量,既可以作为函数的形参,也可以作函数指针变量,既可以作为函数的形参,也可以作函数的实参的实参指针变量作实参时,是将一个变量的地址传送到另指针变量作实参时,是将一个变量的地址传送到另一个函数中一个函数中注意:注意:被调用函数不能改变实参指针变量的值,但被调用函数不能改变实参指针变
8、量的值,但可以改变实参指针变量所指向的变量的值可以改变实参指针变量所指向的变量的值例例7.1.3输入两个整数,按从大到小顺序输出输入两个整数,按从大到小顺序输出swap(p1,p2)int *p1,*p2;int p;p=*p1;*p1=*p2;*p2=p;main()int a,b,*m,*n;scanf(“%d,%d”,&a,&b);m=&a;n=&b;if(ab)swap(m,n);printf(“n%d,%dn”,a,b);运行情况如下:运行情况如下:5,99,5ma&a5&bn9b(a)p1&aa5&bp29b&am&bn(b)p1&aa9&bp25b&am&bn(c)ma&a9&b
9、n5b(d)注:注:swap(p1,p2)int *p1,*p2;int *p;p=p1;p1=p2;p2=p;main()int a,b,*m,*n;scanf(“%d,%d”,&a,&b);m=&a;n=&b;if(ab)swap(m,n);printf(“n%d,%dn”,*m,*n);运行情况如下:运行情况如下:5,95,9ma&a5&bn9b(a)m&aa5&bp29b&ap1&bn(b)ma&a5&bn9b(d)m&aa5&ap29b&bp1&bn(c)注意注意:实参和形参之间是单向的:实参和形参之间是单向的“值传递值传递”,被调用函数不能改变实参指针变量的值,被调用函数不能改变实
10、参指针变量的值,但可以改变实参指针变量但可以改变实参指针变量所指变量所指变量的值的值为了利用被调用函数改变的变量值,应该使为了利用被调用函数改变的变量值,应该使用指针(或指针变量)作函数实参用指针(或指针变量)作函数实参其机制为:在执行被调用函数时,使形参指针变其机制为:在执行被调用函数时,使形参指针变量所指向的变量的值发生变化;函数调用结束后,量所指向的变量的值发生变化;函数调用结束后,通过不变的实参指针(或实参指针变量)将变化通过不变的实参指针(或实参指针变量)将变化的值保留下来的值保留下来例例7.1.4 输入三个数按大小顺序输出输入三个数按大小顺序输出swap(pt1,pt2)int *
11、pt1,*pt2;int p;p=*pt1;*pt1=*pt2;*pt2=p;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);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);运行情况如下:运行情况如下:9,0,10 10,9,07.2 数组的指针和指向数组的
12、指针变量数组的指针和指向数组的指针变量数组的指针:数组的指针:数组的指针数组在内存中的起始地址数组元素的指针数组元素在内存中的起始地址指向数组的指针变量的定义与赋值指向数组的指针变量的定义与赋值int a10,*p;p=a;或:int a10,*p=a;/*将数组a的地址赋给p*/或:int a10,*p=&a0;通过指针引用数组元素通过指针引用数组元素数组元素的引用数组元素的引用:下标法:直观。如:ai指针法:使目标程序占用内存少、运行速度快。如:*(a+i)或*(p+i)通过指针引用数组元素通过指针引用数组元素p+1指向数组的下一个元素,实际变化为p+1*size(size为一个元素占用的
13、字节数)p+i和a+i都是数组元素a i的地址*(p+i)和*(a+i)就是数组元素a i指向数组的指针变量也可以带下标,如pi与*(p+i)等价例例7.2.1 输出数组全部元素输出数组全部元素main()int a 10,*p=a,i;printf(“Input 10 numbers:n”);for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(i=0;i10;i+)printf(“%d ”,ai);printf(“n”);for(i=0;i10;i+,p+)printf(“%d ”,*p);for(p=a;p(a+10);p+)printf(“%d
14、”,*p);说明:说明:指针变量可以实现使本身的值改变,如:指针变量可以实现使本身的值改变,如:for(p=a;p(a+10);p+)printf(“%d ”,*p);而而 for(p=a;a(p+10);a+)printf(“%d ”,*a);是是不不行行的的,因因为为a是是数数组组名名,它它是是数数组组首首地地址址,它的值在程序运行期间是固定不变的它的值在程序运行期间是固定不变的要注意指针变量的当前值要注意指针变量的当前值指指向向数数组组的的指指针针变变量量,可可以以指指向向数数组组以以后后的的内内存存单单元,虽然没有实际意义元,虽然没有实际意义main()int a 10,*p,i;p=
15、a;for(i=0;i10;i+)scanf(“%d”,p+);printf(“n”);p=a;for(i=0;i10;i+,p+)printf(“%d ”,*p);a0a9 p p数组作函数参数数组作函数参数数组名作形参时,接收实参数组的起始地址;作实参时,将数组的起始地址传递给形参数组数组及指向数组的指针变量作函数参数时,实参与形参的对应关系有以下4种情况:(1)形参、实参都用数组名 main()f(x,n)int a10;int x ,n;f(a,10);(2)形参、实参都用指针变量 main()f(x,n)int a10,*p=a;int *x,n;f(p,10);(3)形参用指针变量
16、、实参用数组名 main()f(x,n)int a10;int *x,n;f(a,10);(4)形参用数组名、实参用指针变量 main()f(x,n)int a10,*p=a;int x ,n;f(p,10);例例7.2.2将数组将数组a中中n个整数按相反顺序存放个整数按相反顺序存放void inv(x,n)int x,n;int t,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;t=xi;xi=xj;xj=t;return;main()static int i,a10=3,7,9,11,0,6,7,5,4,2;printf(“The original array:
17、n”);for(i=0;i10;i+)printf(“%d,”,ai);printf(“n”);inv(a,10);printf(“The array has been inverted:n”);for(i=0;iy)z=x;else z=y;return z;main()int a,b,c;int (*p)();p=max;scanf(“%d,%d”,&a,&b);c=(*p)(a,b);printf(“a=%d,b=%d,max=%dn”,a,b,c);说明:说明:函数调用可通过函数名,也可用函数指针调用函数调用可通过函数名,也可用函数指针调用(*p)()表示定义一个指向函数的指针变量,它
18、不是固定指向表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,将哪一个函数地址赋给它,它就指向哪一个哪一个函数的,将哪一个函数地址赋给它,它就指向哪一个函数,在一个程序中,一个指针变量可先后指向不同的函数函数,在一个程序中,一个指针变量可先后指向不同的函数在给函数指针变量赋值时,只需给出函数名而不必给出参数在给函数指针变量赋值时,只需给出函数名而不必给出参数用函数指针变量调用函数时,只需将用函数指针变量调用函数时,只需将(*p)代替函数名即可,代替函数名即可,在在(*p)后后括号内根据需要写上参数括号内根据需要写上参数对指向函数的指针变量,对指向函数的指针变量,p+n、p+、p-等运
19、算无意义等运算无意义例例7.4.2把指向函数参数的指针变量作函数参数把指向函数参数的指针变量作函数参数main()int max(),min(),add();int a,b;printf(“enter a and b:”);scanf(“%d,%d”,&a,&b);printf(“max=“);process(a,b,max);printf(“min=“);process(a,b,min);printf(“sum=“);process(a,b,add);max(x,y)int x,y;int z;if(xy)z=x;else z=y;return z;min(x,y)int x,y;int z
20、;if(xy)z=x;else z=y;return z;add(x,y)int x,y;int z;z=x+y;return z;process(x,y,fun)int x,y;int(*fun)();int result;result=(*fun)(x,y);printf(“%dn”,result);运行情况如下:运行情况如下:enter a and b:2,6max=6min=2sum=87.5 返回指针值的函数返回指针值的函数 一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址返回指针值的函数(简称指针函数)的定义格式:函数类型函数类型 *函数名函数名(参数表
21、参数表);如:如:int *a(x,y);例例7.5.1 有若干学生的成绩(每个学生有4门课程),要求输出有不及格课程的学生的学号和成绩。用指针函数实现。607080905089678834789066pointerpointer+150789066*pointerPt(当有不及格时)*(pointer+1)Pt(当无不及格时)main()static int score 4=60,70,80,90,50,89,67,88,34,78,90,66;int i,j,*p;/*定义一个(列)指针变量p*/int *search();for(i=0;i3;i+)/*控制每个学生*/p=search(
22、score+i);/*用行指针作实参,调用search()函数*/if(p=*(score+i)/*该学生至少有一项成绩不合格*/*输出该学生的序号和各项成绩*/printf(“No.%d scores:”,i+1);for(j=0;j4;j+)printf(“%d ”,*(p+j);printf(“n”);int *search(pointer)int(*pointer)4;int i=0;int *pt;/*定义一个(列)指针变量pt*/pt=*(pointer+1);/*使pt指向下一行之首(作标志用)*/for(;i4;i+)if(*(*pointer+i)60)/*某项成绩不合格*/
23、pt=*pointer;/*使pt指向本行之首*/break;/*退出循环*/return(pt);程序运行情况如下:No.2 scores:50 89 67 88No.3 scores:34 78 90 66 7.6 指针数组和指向指针的指针指针数组和指向指针的指针指针数组指针数组概念:概念:数组的每个元素都是一个指针类型数据,即指针数组中的每一个元素都是指针变量定义格式:数据类型数据类型 *数组名数组名数组长度说明数组长度说明;例如:例如:int *p4;上述定义说明数组p是指针类型,共有4个元素,每个元素可指向一个整型变量。int (*p)4;/*p是一个指向有4个元素的数组的指针变量*
24、/例例7.6.1 将若干字符串按字母顺序输出将若干字符串按字母顺序输出void sort(name,n)char*name;int n;char*temp;int i,j,k;/*使用选择法排序使用选择法排序*/for(i=0;in-1;i+)/*外循环:控制选择次数外循环:控制选择次数*/k=i;/*预置本次最小串的位置预置本次最小串的位置*/for(j=i+1;j0)k=j;/*存在更小的串保存之存在更小的串保存之*/if(k!=i)/*存在更小的串,交换位置存在更小的串,交换位置*/temp=namei,namei=namek,namek=temp;void print(name,n)c
25、har*name ;int n;int i;for(i=0;in;i+)printf(“%sn”,namei);main()char*name=“BASIC”,”FORTRAN”,”PASCAL”,”C”,”FoxBASE”;int n=5;sort(name,n);/*使用字符指针数组名作实参,调用排序函数使用字符指针数组名作实参,调用排序函数sort()*/print(name,n);/*输出排序结果输出排序结果*/程序运行结果:程序运行结果:BASICCFORTRANFoxBASEPASCALname0BASICname1FORTRANname2PASCALname3Cname4FoxB
26、ASEname指针数组指针数组name0BASICname1FORTRANname2PASCALname3Cname4FoxBASEname指针数组指针数组排序前排序前排序后排序后指向指针的指针指向指针的指针设置一个指针变量p,使其指向指针数组的元素(元素的值还是一个指针),称p为指向指针的指针变量显然,指向指针的指针变量是一个两级的指针变量指向指针的指针变量的定义指向指针的指针变量的定义:数据类型数据类型 *指针变量指针变量,*指针变量指针变量2;如:char *p;指向指针的指针变量的赋值指向指针的指针变量的赋值:指针变量指针变量=指针数组名指针数组名+i;如:p=name+2;例例7.6
27、.2main()char*name=“BASIC”,”FORTRAN”,”PASCAL”,”C”,”FoxBASE”;int i;char *p;for(i=0;i5;i+)p=name+i;printf(“%sn”,*p);运行结果如下:运行结果如下:BASICFORTRANPASCALCFoxBASE例例7.6.3main()static a5=1,3,5,7,9;static int*num5=&a0,&a1,&a2,&a3,&a4;int*p,i;p=num;for(i=0;i1)printf(“%st”,*argv);-argc;输入的命令行参数为:输入的命令行参数为:file1 C
28、hina Beijing运行结果为:运行结果为:China BeijingTurbo C动态存储分配动态存储分配 在程序运行过程中,数组的大小是不能改变的。这种数组称为静态数组。静态数组的缺点是:对于事先无法准确估计数据量的情况,无法做到既满足处理需要,又不浪费内存空间动态数组是指动态数组是指,在程序运行过程中,根据实际需要指定数组的大小 在C语言中,可利用内存的申请和释放库函数,以及指向数组的指针变量可当数组名使用的特点,来实现动态数组动态数组的本质是动态数组的本质是:一个指向数组的指针变量一个指向数组的指针变量(1)库函数malloc()调用方式:调用方式:void*malloc(unsi
29、gned size)功能功能:在内存的动态存储区分配个长度为size的连续空间返回值返回值:申请成功,则返回新分配内存块的起始地址;否则,返回NULL函数原型函数原型:alloc.h,stdlib.hmalloc()函数的返回值是一个无类型指针,其特点是可以指向任何类型的数据。但在实际使用malloc()函数时,必须将其返回值强制转换成被赋值指针变量的数据类型,以免出错(2)运算符sizeof格式格式:sizeof(变量名类型名)功能功能:求变量类型占用的内存字节数(正整数)如:在IBM-PC机上,sizeof(int)=2库函数库函数free()调用方式:调用方式:void free(voi
30、d *ptr)功能:释放由功能:释放由ptr指向的已分配的内存区域,并返还给自由内指向的已分配的内存区域,并返还给自由内存区存区free只能用于已由只能用于已由malloc()或或calloc()分配地址的指针来调用分配地址的指针来调用原则上,原则上,使用使用malloc()函数申请的内存块,操作结束后,应函数申请的内存块,操作结束后,应及时使用及时使用free()函数予以释放。函数予以释放。尤其是循环使用尤其是循环使用malloc()函函数时,如果不及时释放不再使用的内存块,很可能很快就耗数时,如果不及时释放不再使用的内存块,很可能很快就耗尽系统的内存资源,从而导致程序无法继续运行尽系统的内
31、存资源,从而导致程序无法继续运行#include “alloc.h”#include “stdlib.h”main()char *str;if(str=(char*)malloc(50)=NULL)is failed.”);exit(1);/*内存申请失败:提示,退出内存申请失败:提示,退出*/else printf(“nInput string:”);gets(str);puts(str);free(str);运行情况如下:运行情况如下:Input string:good morninggood morning指针小结指针小结int i;定义整型变量定义整型变量iint *p;P为指向整型数
32、据的指针变量为指向整型数据的指针变量int an;定义整型数组定义整型数组a,它有它有n个元素个元素int*pn;定义指针数组定义指针数组p,它由它由n个指向整型数据的指针元素组成个指向整型数据的指针元素组成int(*p)n;P为一指向含有为一指向含有n个元素的一维数组的指针变量个元素的一维数组的指针变量int f();f为一带回整型函数值的函数为一带回整型函数值的函数int*p();p为带回一个指针的函数,该指针指向整型数据为带回一个指针的函数,该指针指向整型数据int(*p)();函数的指针,该函数返回一个整型值函数的指针,该函数返回一个整型值int*p;p为指向一个整型数据的指针变量的指针为指向一个整型数据的指针变量的指针 int amn;int *p=a;int (*pa)n=a;则数组元素则数组元素aij的地址为:的地址为:&aij=p+i*n+j=*(pa+i)+j数组元素数组元素aij为:为:aij=*(p+i*n+j)=*(*(pa+i)+j)