《第7章 指针.ppt》由会员分享,可在线阅读,更多相关《第7章 指针.ppt(41页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第7章章 指针指针魏东平目录指针的概念变量与指针一维数组与指针二维数组与指针指针的应用魏东平7.1 7.1 指针的概念指针的概念计算机的内存地址在计算机中,内存中的程序和数据都是以二进制形式存放的,存储单位为字节(Byte),1个字节占8个二进制位(bit),即1B=8bit计算机的内存大小用所拥有的存储单元的个数来衡量对计算机的所有内存单元进行统一编号,每个存储单元都有一个惟一的编号,称为该存储单元的地址编码,简称地址魏东平饭店客房管理有3个人临时相约在某饭店小聚,A先到饭店,在服务台登记了房间1088,然后电话通知了B,但未告知C。显然,B和C的到达方法会有所不同,B可以直奔1088房间
2、,而C呢?可以到服务台查到A所登记的房号1058106810881098客人A魏东平访问内存中的数据程序运行时所有程序指令和数据都存放在内存,占用存储单元。存储单元中的指令或数据可称为该单元的内容。不同类型的内容所占据的存储单元的个数不同。通常,把一个数据所占据的若干存储单元中第一个单元的地址称为该数据的地址。计算机中,内存的操作有两种,即“写”和“读”。所谓“写”是把内容按地址存入对应的存储单元的过程,所谓“读”是获取(但不消除)某地址中的内容的过程程序运行时所占用的存储单元,在程序运行结束后会被操作系统回收魏东平要访问存放在某存储单元中的数据,可以直接访问,也可以间接访问。所谓直接访问是指
3、可以直接获取内存中的数据。所谓间接访问是指如果某数据的地址是已知的,则可以通过地址间接访问该数据。1AD02468ACE3.51AD2变量a指针p魏东平指针C语言中,用指针变量存放地址值使用指针不能仅可以访问变量,也可以访问数组或其他指针,甚至可以访问函数(即程序指令)等魏东平7.2 7.2 变量与指针变量与指针指针变量的定义“定义变量”也就是为变量分配内存空间。指针变量的值是一个地址,指针变量的类型是存放在该地址存储单元中的数据的类型,也就是该指针所指向的数据的类型定义指针变量的方法是:类型说明类型说明*指针变量名指针变量名其中,“类型说明”可以是C语言的基本数据类型,如char、int、f
4、loat、double等,也可以是用户定义的复杂数据类型,如结构体等。星号“*”称为指针说明符,表示后边的标识符为指针变量名魏东平可以同时定义多个指针变量,各变量名用逗号,同时在每个变量名的前边加星号“*”格式如下:类型说明类型说明 *变量名变量名1,*变量名变量名2,例如:int *p2,*p3;指针变量可以与其他变量一起定义例如:int i,a5,*p;魏东平指针变量的值变量的地址C语言程序中的变量都必须“先定义,后使用”变量的定义有两层含义,首先是为变量分配内存,其次是为变量赋值例如:int x,y;x=3;y=x;“&”为取地址运算符,可作用于任何类型的变量,一般格式为:&变量名取地址
5、运算表达式的返回值是一个地址yx(a)int x,y;3yx(b)x=3;3yx(c)y=x;3魏东平指针变量的赋值指针变量的值是存储单元的地址,虽然可以理解为整数,但不能直接用整数为指针变量赋值int *p;p=0 x1AB0;/*错误*/要为指针变量赋值,可以用已定义的相同类型的普通变量的地址,也可以是已经赋值的另一个相同类型的指针变量的值int x;int *p,*q;p=&x;q=p;魏东平需要特别注意的是,程序中永远不要让指针包含一个未知的地址!如果程序中暂时还不能确定指针的指向,或者不需要指向某个特定的存储地址,则可以用空指针NULL(或0)为指针赋值方法如下:int *p,*q;
6、p=NULL;/*用空指针赋值*/q=0;/*同样是空指针*/在定义指针变量的同时,也可以初始化int x=3;/*变量x的初始化*/int *p=&x;/*指针p用x的地址初始化*/int *q=p;/*指针q用指针p初始化*/int *r=NULL;/*指针r用空指针初始化*/可以用NULL为任何类型的指针赋值,甚至为空类型的指针(用void声明)赋值void类型的指针可指向任何类型的变量,常作为通用的指针例如:void *p;int x;float y;p=&x;p=&y;魏东平指针变量的引用指针运算符“*”的运算规则是:*指针变量名指针变量名指针变量名指针变量名其运算结果是该指针变量所
7、指向的变量的值当指针指向某个确定的地址时,可以通过指针运算符“*”引用所指向的数据例如:int x=3,y;int *p=&x;y=*p;*p=5;3yx(a)int x=3,y;(c)y=*p;2EA22ED03yx2EA22EAD2ED02ED0p33yx2EA22EAD2ED02ED0p(d)*p=5;35yx2EA22EAD2ED02ED0p(b)int *p=&x;魏东平指针运算符“*”与取地址运算符“&”都是单目运算符,优先级和其他单目运算符相同,高于算术运算符。单目运算符都是右结合的若有int y,x=3,*p=&x,则y=10*p是合法的,也可以写作y=*p*10,但y=x*1
8、0是非法的&*p等价于p,而*&a等价于a,但p必须是指针变量,a可以是任何类型的变量一般不能将指针运算符“*”直接应用于void类型的指针,必须使用强制类型转换魏东平应用举例用指针实现求两个数的和#include void main()int a=5,b=3,sum;int*pa=&a;int*pb=&b;sum=*pa+*pb;printf(“%d+%d=%d”,a,b,sum);1魏东平用指针实现求10个数的和#include void main()int i,x,sum;int*p1=&x;int*p2=∑*p2 =0;printf(输入10个整数:);for(i=0;i10;
9、i+)scanf(%d,p1);*p2=*p2+*p1;printf(累加和为%d,*p2);2魏东平用指针实现求1100的累加和#include void main()int i,x=1,sum=0;int *p1=&x;int *p2=∑for(i=0;i100;i+)*p2+=(*p1)+;printf(1+2+.+100=%dn,sum);3魏东平7.3 一维数组与指针一维数组的地址对于int a5=3,5,2,1,4,设数组的首地址为508A,每个元素占4个字节,则元素a0、a1、a2、a3、a4 的地址依次为508A、508E、5092、5096、509A数组元素ai的地址
10、是&ai第一个数组元素的地址称为数组的首地址,用数组名表示,所以数组名a被定义为&a0数组元素ai的地址可表示为a+i,也就是说对于数组a,a+i就是&ai数组元素ai可用*(a+i)表示508A508E50925096 509A35214aa+1a+2a+3a+4魏东平打印数组#include void main()int i,a5=5,3,1,2,4;for(i=0;i5;i+)printf(%d ,*(a+i);4魏东平指向数组元素的指针指向数组元素的指针变量若有int a5,*p,可以令指针p指向任何一个数组元素ai,方法是令p=&ai,也可以写为p=a+i若指针p指向数组a的第一个元
11、素,即p=a=&a0,则p+i指向ai,*(p+i)就是ai若指针p和数组a的类型相同,且p=a,则数组a的第i个数组元素的地址可写为a+i、p+i、&ai 或&pi,该元素的值可表示为ai、*(a+i)、*(p+i)或 pi魏东平指针的运算与指针相关的运算除了“=”、“&”和“*”,还有4种:指针与整数的加、减法指针指针指针指针 整数整数整数整数若指针p指向数组a第i个元素ai,则p+1指向下一个元素ai+1,而p-1指向前一个元素ai-1左移指针“-”和右移指针“+”指针指针指针指针+或+指针指针指针指针指针指针指针指针-或-指针指针指针指针若指针p指向数组a的第i个元素ai,则p+使指针
12、右移一位,指向ai+1,而p-则使指针左移一位,指向ai-1指针与指针的减法指针指针指针指针指针指针指针指针若指针p和q分别指向数组a的两个元素ai和aj,则p-q的值为i-j指针的关系运算指针指针指针指针 关系运算符关系运算符关系运算符关系运算符 指针指针指针指针若指针p和q分别指向数组a的两个元素ai和aj,则p和q之间的关系为:若ij,则pj,则pq魏东平打印数组#include void main()int i,a5=5,3,1,2,4;int*p=a;for(i=0;i5;i+)printf(%d ,*p+);5*+p和+*p两个表达式是等价的吗?为什么?魏东平内存的动态分配C语言中
13、,数组长度是固定的,也就是说,不能定义可变长度的数组。然而在现实生活中,要处理的数据的规模有时是难于预期的,这就要使用动态内存分配技术了C语言所提供的有关函数有3个,即malloc函数、calloc函数和free函数,它们定义在头文件stdlib.h中魏东平u malloc函数malloc函数的使用方法是:指针指针指针指针=(=(类型说明类型说明类型说明类型说明*)malloc()malloc(数据长度数据长度数据长度数据长度)其中,“(类型说明*)”是强制类型转换,以保证与指针的类型一致。“数据长度”为一正整数,表示数据所占内存单元个数字节数,常用sizeof()运算符来获取malloc函数
14、的函数值为成功分配的内存单元的地址,若分配内存失败则返回空指针NULL例如int*p;p=(int*)malloc(sizeof(int);*p=3;魏东平sizeof()运算符sizeof的用法是:sizeof(sizeof(运算对象运算对象运算对象运算对象 )表达式的值是“运算对象”所占内存的存储单元个数“运算对象”可以是常量、变量,也可以是类型说明符sizeof(123)返回存放1个整数的内存长度对于float x=123.45,sizeof(x)返回变量x的内存长度对于int a5,sizeof(a)返回数组a的内存长度,即可以存放5个整数的存储空间的字节数,不是数组长度sizeof(
15、“apple”)返回字符串的内存长度,包含字符串的结束标记0sizeof(int)返回存放int型整数的内存长度使用sizeof()运算符可提高C语言程序的可移植性魏东平u calloc函数calloc函数的使用方法是:指针指针指针指针=(=(类型说明类型说明类型说明类型说明 *)calloc()calloc(数据个数数据个数数据个数数据个数,数据长度数据长度数据长度数据长度)与malloc函数不同的是,calloc函数可分配若干个数据所占据的连续空间,因此可将calloc函数分配的空间与等长度的数组对应,而malloc函数只能分配一个变量地址例如:int*p,n=5;p=(int*)mall
16、oc(n,sizeof(int);*p=1;p3=4;魏东平u free函数为了有效地使用内存资源,程序中动态分配的内存空间必须在使用结束后立即释放,方法是调用free函数free函数的使用方法是:free(free(指针指针指针指针););作用是释放“指针”所指向的动态分配的内存魏东平打印数组求若干整数中的最大值分析:在程序运行时输入要处理的数值的个数#include#include void main()int n;int*pData,*p,*pMax;printf(数据个数为?);scanf(%d,&n);if(pData=(int*)calloc(n,sizeof(int)=NULL)
17、printf(内存分配失败n);exit(0);printf(它们是?);for(p=pData;ppData+n;p+)scanf(%d,p);pMax=pData;for(p=pData+1;p pData+n;p+)if(*pMax *p)pMax=p;printf(第%d 个数最大,为%dn,pMax-pData+1,*pMax);free(pData);6魏东平应用举例用指针实现将数组倒置#include#define N 5void main()int aN=5,4,3,2,1;int *p=a;int *q=a+N-1;int i,t;while(pq)t=*p;*p=*q;*q
18、=t;p+;q-;for(i=0;iN;i+)printf(%5d,ai);7开始54321pq循环1次14325pq循环2次12345pq结束12345魏东平在数组中任意位置插入一个新元素#include#define N 100void main()int iListN,i,l,x,n;int*p;printf(插入前数字个数(1%d)为?,N-1);do scanf(%d,&n);while(nN-1);printf(顺序输入%d个数:,n);p=iList;for(i=0;il;i-)*p=*(p-1);p-;*p=x;printf(插入后的结果为:);p=iList;for(i=0;
19、i=n;i+)printf(%5d,*p+);8魏东平7.4 二维数组与指针二维数组的元素的地址数组aMN的元素的排列顺序是a00、a01、a0N-1、a10、aM-1N-1;若第1个元素元素的位置为0,则元素aij的位置是i*N+j元素aij的地址为&aij若指针变量p的类型与二维数组a的类型相同,则p可指向任一数组元素,即p=&aij若指针p=&a00,则指向元素aij的指针为p+i*N+j若指针p指向元素aij,则p+使p指向下一元素,可能是同一行的下一元素aij+1(j0时)或指向上一行的最后一个元素ai-1N-1(j=0时)魏东平打印二维数组#include#define N 3vo
20、id main()int i,aNN=1,2,3,4,5,6,7,8,9;int *p;p=&a00;p=&a00;for(i=0;iN*N;i+)printf(%5d,*p+);if(i+1)%N=0)printf(n);9p=&a00能否用p=a代替呢?魏东平指向数组的指针二维数组的行地址C语言中,二维数组aMN可以看作是由M个一维数组组成的一维数组,该一维数组的元素是a0、a1、aM-1数组名称a是该一维数组的首地址,也就是第一元素a0的地址a是第1行的地址,a+1是第2行的地址,二维数组的每一行也是一个一维数组,由N个元素组成第1行对应的数组名为a0,元素为a00、a01、a0N-1第
21、2行对应数组a1,元素为a10、a11、a1N-1对于二维数组a,ai、a+i表示第i行的行地址,第i行第j个元素的地址为ai+j、*(a+i)+j,aij元素为*(*(a+i)+j)a02a01a00a03a0a0+1a0+2a0+3a12a11a10a13a1a1+1a1+2a1+3a22a21a20a23a2a2+1a2+2a2+3a2a1a0aa+1a+2一维数组一维数组a一维数组一维数组a0一维数组一维数组a1一维数组一维数组a2ap魏东平指向数组的指针与二维数组对应的指针是指向一个一维数组的指针,定义格式为:类型说明类型说明类型说明类型说明 (*(*指针名称指针名称指针名称指针名称
22、)整型常数整型常数整型常数整型常数 其中,圆括号不能省略,否则为定义指针组成的数组例如,int a34,(*p)4;p=a+1;若指针p指向二维数组a的第i行,即p=a+i,则p+使p指向下一行,p-使p指向上一行魏东平指向指针的指针如果指针的值是另一指针的地址,则该指针是指针的指针,定义为:类型说明类型说明类型说明类型说明*指针变量名指针变量名指针变量名指针变量名例如,#include void main()int x=3,*p1=&x;int *p2;p2=&p1;printf(%d,*p2);魏东平指针数组如果数组的每个元素都是指针,则该数组为指针数组,定义为:类型说明类型说明类型说明类
23、型说明 *数组名数组名数组名数组名 数组长度数组长度数组长度数组长度 例如:#include void main()int i,x5=1,2,3,4,5;int *p13;int *p2;for(i=0;i3;i+)p1i=&x2*i;for(p2=p1;p2=p1+2;p2+)printf(%5d,*p2);12345x&x0&x2&x4p1p2&p11x0 x1x2x3x4p10p11p12魏东平7.5 指针的应用数组中包含n个整数,求最大数的位置#include#define N 100void main()int i,n;int iDataN,*p,*pMax;printf(共有几个数
24、(1%d)?,N);scanf(%d,&n);printf(它们是:);for(p=iData;piData+n;p+)scanf(%d,p);pMax=iData;for(p=iData;p*pMax)pMax=p;i=pMax-iData+1;printf(第%d 个数最大,为%dn,i,*pMax);10魏东平用选择法将数组iData中的数值排序11选择法排序的思路是:求第1n个数中的最小值的位置i,然后把该数与第1个数交换,这样,第1个数为最小,以后不再考虑;求第2n个数中的最小值的位置i,与第2个数交换,这样,第2个数为次最小,也不再考虑;求第3n个数中的最小值的位置i,与第3个数交
25、换;依次类推#include#define N 100void main()int n;int iTemp,iDataN;int*p1,*p2,*pMin;printf(共有几个数(1%d)?,N);scanf(%d,&n);printf(它们是:);for(p1=iData;p1iData+n;p1+)scanf(%d,p1);for(p1=iData;p1iData+n;p1+)pMin=p1;for(p2=p1+1;p2iData+n;p2+)if(*p2 *pMin)pMin=p2;iTemp=*pMin;*pMin=*p1;*p1=iTemp;printf(排序后:);for(p1=
26、iData;p1iData+n;p1+)printf(%d,*p1);魏东平将数组iSrc复制到数组iDest中12#include#define N 100void main()int n;int iSrcN,iDestN;int *pSrc,*pDest;printf(共有几个数(1%d)?,N);scanf(%d,&n);printf(它们是:);for(pSrc=iSrc;pSrc iSrc+n;pSrc+)scanf(%d,pSrc);pSrc=iSrc;pDest=iDest;while(pSrc iSrc+n)*pDest=*pSrc;pSrc+;pDest+;printf(复制
27、后:);for(pDest=iDest;pDest iDest+n;pDest+)printf(%d,*pDest);魏东平求二维数组iDataMN中最大元素所在的行和列13对于有m行n列的二维数组,根据数组元素的存储顺序可知,若数组中的第k个元素为iDataij,则有i=k/N,j=k-i*N=k%N,这里i、j都是整数,“%”为求余数运算#include#define M 3#define N 4void main()int i,j;int iDataMN;int *p,*pMax;printf(请按行输入%dx%d数组的各个元素:n,M,N);for(p=&iData00;p=&iDataM-1N-1;p+)scanf(%d,p);printf(输入的数组是:);for(p=iData0;p=iDataM-1+N-1;p+)if(p-iData0)%N)=0)printf(n);printf(%5d,*p);pMax=iData0;for(p=iData0;p*pMax)pMax=p;i=(pMax-iData0)/N;j=(pMax-iData0)%N;printf(n最大值在第%d 行第%d 列n,i+1,j+1);谢谢本章结束
限制150内