C语言第10章(谭浩强).ppt





《C语言第10章(谭浩强).ppt》由会员分享,可在线阅读,更多相关《C语言第10章(谭浩强).ppt(80页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第10章 指针 指针可以有效地表示复杂的数据结构;能动态的分配内存、使用字符串和数组;能在调用函数时获得1个以上的结果;能直接处理内存单元地址等。掌握指针的应用,可以使程序简洁、紧凑、高效。110.1地址和指针的概念地址和指针的概念一、一、变变量的地址量的地址计算机内存区的每一个字节都有一个编号。计算机内存区的每一个字节都有一个编号。在在对对程程序序进进行行编编译译时时,系系统统会会给给变变量量分分配配内内存存单单元元,这这个个内内存存单单元元的的地地址址就就是是变变量量的的地地址址。系系统统根根据据不不同同的的数数据据类类型型分分配配不同字节的空间不同字节的空间。内存单元地址内存单元地址内存
2、单元内容内存单元内容不同不同i3jk69变量名变量名200020022004地址地址编译时是把变量名转换为变量的地址编译时是把变量名转换为变量的地址如:如:scanf(“%d”,&i);printf(“%d”,j);k=i+j;2二、变量的访问方式二、变量的访问方式1.1.直接访问直接访问 按变量地址存取变量值的方式称为按变量地址存取变量值的方式称为“直接访问直接访问”方式。方式。2.2.间接访问间接访问 假如定义变量假如定义变量j j 存放变量存放变量i i的地址。的地址。i32000变量名变量名2000地址地址 j如:如:j=&i;先找到先找到j得到变量得到变量i的地址的地址找到变量找到变
3、量i的存储单元的存储单元对它进行存取访问对它进行存取访问3三、指针变量三、指针变量由由于于通通过过地地址址可可以以找找到到所所需需变变量量的的存存储储单单元元,所所以以c语语言言把地址称为指针。把地址称为指针。指针指针:一个变量的地址称为该变量的指针。:一个变量的地址称为该变量的指针。例如:地址例如:地址2000是变量是变量i的指针。的指针。指针变量指针变量:专门存放变量地址的变量叫指针变量。:专门存放变量地址的变量叫指针变量。注意:注意:指针指针和和指针变量指针变量的的区别区别如:如:j j 为指针变量,它存放整型变量为指针变量,它存放整型变量i i的地址的地址 我们称我们称,指针变量,指针
4、变量 j j 指向指向整型变量整型变量i i410.2变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量变量的指针变量的指针就是变量的就是变量的地址地址。存存放放变变量量地地址址的的变变量量是是指指针针变变量量,用用来来指指向向另另一一个变量。个变量。5注意:注意:在在c程序中用程序中用*表示指向,若定义了表示指向,若定义了i_pointer为指针变量,那么为指针变量,那么*i_pointer就是就是i_pointer指向的那个变量。指向的那个变量。*i_pointer相当于相当于i都代表都代表3(值值)/*指针指针i_pointer指向了变量指向了变量i*/一一、如何定义一个指针变
5、量、如何定义一个指针变量形式:基类型形式:基类型*指针变量名指针变量名指针只能指向基类型规定的类型变量指针只能指向基类型规定的类型变量例如:例如:inti,j;floatx;inti,j;floatx;int*i_pointer,*j_pointer;int*i_pointer,*j_pointer;那么,如何使一个指那么,如何使一个指针变针变量指向另一个量指向另一个变变量呢?量呢?可以可以:i=3;i=3;i_pointer=&i;i_pointer=&i;j_pointer=&j;j_pointer=&j;6在定义指针变量时注意:(1)定义指针变量时,变量前面的*是表示该变量是指针型的,其
6、变量名是i_pointer,而不是*i_pointer(2)定义指针变量必须指定其类型。为什么?当i_pointer+时,加1代表多少字节才能确定。总结:一个指针变量只能指向同一类型的变量。如:floata;int*pointer;pointer=&a;(错错错错)7二、二、指针变量的引用指针变量的引用指针变量中只能存放指针变量中只能存放地址地址(指针)(指针)两个运算符:1.&:取地址运算符 如:&a/*变量a的地址*/2.*:指针运算符,取其指向的内容 *pointer表示求指针变量pointer所指向变量的内容(值)。如:inti=3,c;int*p;/*表示定义指针型变量p*/p=&i
7、;/*指针变量p指向了变量i*/c=*p;强调*定义和引用时的区别8输出:输出:100,10100,10*pointer_1=&a;*pointer_2=&b;例10.1 通过指针变量访问整型变量main()int a,b;int*pointer_1,*pointer_2;/*区分定义和引用时的区别*/a=100;b=10;pointer_1=&a;pointer_2=&b;printf(“%d,%dn”,a,b);printf(“%d,%dn”,*pointer_1,*pointer_2);9说明:若:p1=&a;/*假设 p1 和 p2 是指针*/p2=&*p1;p2=&a /*p2也指向
8、了a*/(1)&*p1 的含义是什么?&和*优先级相同,按自右至左的方向结合,先进行*p1的运算,就是变量a,再执行&运算。&*p1&a(2)*&a 的含义是什么?先进行&a的运算,得a的地址,再进行*运算,就是变量a。*&aa 或 *&a*p110说明:若:p1=&a;(3)(*p1)+a+(*p1)+必须有括号,若没有括号:*p1+/*优先级别相同,为右结合*/*(p1+)/*由于+在后,先使用p1,得到*p的值,p1再加1,p1指向了下一个地址*/11运行:运行:5,9a=5,b=9max=9,min=5注意:a和b并没有交换,保持原值,但是p1和p2的值改变了。例例10.2输入输入a和
9、和b两个整数,按大小的顺序输出两个整数,按大小的顺序输出.main()int*p1,*p2,a,b;scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)p1=&b;p2=&a;printf(“a=%d,b=%dn”,a,b);printf(“max=%d,min=%dn”,*p1,*p2);12 三、三、指针变量作为函数参数指针变量作为函数参数 函数的参数可以是整型、实型、字符型等数据或者是数组,还可以是指针类型的。它的作用是将一个变量的地址传送到另一个函数中。13例例10.3同例同例10.2输入输入a和和b两个整数,按大小的顺序输出两个整数,按大小的顺序输出.mai
10、n()int*p1,*p2,a,b;scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(ab)swap(p1,p2);printf(“n%d,%dn”,a,b);voidswap(int*p1,int*p2)inttemp;temp=*p1;*p1=*p2;*p2=temp;/*指针变量作函数参数,把变量指针变量作函数参数,把变量a和和b的的地址传给形参,这时实参和形参都指向地址传给形参,这时实参和形参都指向变量变量a和和b*/*定义形参,所以要带定义形参,所以要带*/*把变量把变量a和和b的的值交换值交换*/注意:a和b的值改变了。14指针变量作函数参数时,指针变量作函数
11、参数时,注意注意:1.指针变量,既可以作为函数的形参,也可指针变量,既可以作为函数的形参,也可以作函数的实参。以作函数的实参。2.指针变量作实参时,与普通变量一样,也指针变量作实参时,与普通变量一样,也是是“值传递值传递”,即将指针变量的值(,即将指针变量的值(一个地址一个地址)传递给被调用函数的形参(必须是一个指针变量)传递给被调用函数的形参(必须是一个指针变量)。注意:注意:被调用函数不能改变实参指针变量的被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。值,但可以改变实参指针变量所指向的变量的值。15 例例10.4输入输入a、b、c3个整数,按大小顺序输出。个整
12、数,按大小顺序输出。voidswap(int*pt1,int*pt2)/*指针变量作函数形数指针变量作函数形数*/inttemp;temp=*pt1;*pt1=*pt2;*pt2=temp;/*交换变量交换变量*/voidexchange(int*q1,int*q2,int*q3)/*判断大小判断大小*/if(*q1*q2)swap(q1,q2);/*指针变量作函数实参指针变量作函数实参*/if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);main()inta,b,c,*p1,*p2,*p3;scanf(“%d,%d,%d”,&a,&b,&c);p1=&a
13、;p2=&b;p3=&c;exchange(p1,p2,p3);/*指针变量作函数实参指针变量作函数实参*/printf(“n%d,%d,%dn”,a,b,c);1610.3数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量既然指针可以指向变量,当然也能指向数组。既然指针可以指向变量,当然也能指向数组。数组的元素是数组的元素是连续存放连续存放的的:一般,用一般,用下标法下标法表示数组元素,如:表示数组元素,如:a310.3.1指向数组元素的指针指向数组元素的指针 如何定义指向数组的指针变量?定义与指向普通变量的指针变量的定义方法一样。例如:inta10,*pointer=a;或者:或
14、者:inta10,*pointer;pointer=a;以上是在语句中赋值,分为两步。&a0或注意:如果数组为注意:如果数组为int型,型,则指针变量也必须为则指针变量也必须为int型。型。&a0或/*数组名代表数组的首地址*/以上是在定义时赋值17int *p1,*p2,*p3;int a5=2,4,8,16,32 ;p1=&a0;p2=&a3;p3=a;2481632a0a1a2a3a4p1p2p31810.3.2通过指针引用数组元素通过指针引用数组元素如:如:inta3,*p=a;*p=1;/*相当于相当于a0=1*/(p=1;)(错错)注意:当p+1p+1时,则指针p指向同一数组的下一
15、个元素,而不是把地址加1。当p为int型时:p+1相当于使p的值(地址)加2个字节;当p为float型时:p+1相当于使p的值(地址)加4个字节;所以:p+1代表的地址=p+1*d/*d为数组元素的类型所占的字节数*/19说明:说明:如果有如果有inta10,*p=a;,则:,则:(1)p+i和和a+i都可以表示数组元素都可以表示数组元素ai的的地址地址,或者说它们都指向或者说它们都指向a数组的第数组的第i个元素。个元素。例如:例如:p+9a+9(2)*(p+i)和和*(a+i)就是数组元素就是数组元素ai的值。的值。例如:例如:*(p+5)*(a+5)值都是值都是&a9,都指向,都指向a9/
16、*是地址是地址*/都是都是a5/*是值是值*/实际上,在编译时,对数组元素实际上,在编译时,对数组元素ai是按是按*(a+i)处理的,若数组处理的,若数组a的首地址为的首地址为1000,a3的地址的地址=1000+3*2=1006,再到地址,再到地址1006找到找到a3的值。的值。20说明:说明:(3)指向数组的)指向数组的指针指针变量,也可将其看作是变量,也可将其看作是数组数组名名,因而也可按下标法来使用。,因而也可按下标法来使用。例如:例如:*(p+i)=pi=ai所以:引用一个数组元素,可以用多种方法所以:引用一个数组元素,可以用多种方法:1)下标法下标法,如,如ai或或pi形式;形式;
17、2)指针法指针法,如,如*(a+i)或或*(p+i)/*p是指针变量是指针变量*/*a是数组名,是数组名,p是指针变量是指针变量*/21 例例10.5 输出数组中的全部元素。比较三种方法(1)下标法void main()int a10,i;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(i=0;i10;i+)printf(“%d”,ai);printf(“n”);(3)用指针变量指向数组元素void main()int a10,i,*p;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(p=a;p(a+1
18、0);p+)printf(“%d”,*p);printf(“n”);(2)用数组名计算数组地址,找到元素的值void main()int a10,i;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(i=0;i10;i+)printf(“%d”,*(a+i);printf(“n”);第第1、2种方法效率相同,第种方法效率相同,第3种方法的效率更高种方法的效率更高for(i=0,p=a;p(a+10);p+)for(i=0,p=a;p(a+10);p+)printf(%d,printf(%d,pipi););22使用指针变量指向数组元素时,需使用指针变
19、量指向数组元素时,需注意注意:(1)可以通过改变指针变量的值使其指向不同的元素,可以通过改变指针变量的值使其指向不同的元素,如如p+但是不能用但是不能用数组名数组名a+(2)使用指针变量,要注意指针的当前值。使用指针变量,要注意指针的当前值。如下例如下例main()int*p,i,a5;p=a;for(i=0;i5;i+)scanf(“%d”,p+);printf(“n”);for(i=0;i5;i+,p+)printf(“%d”,*p);printf(“n”);p=a;/*输出数组元素输出数组元素*/解决办法:解决办法:?(3)由上例得出,指针变量可以指向数组以外的内存单元,系统不会)由上例
20、得出,指针变量可以指向数组以外的内存单元,系统不会报错。报错。23*(p+)a0*(+p)a1若若pa0,则,则注意注意:(4)指针变量的运算。指针变量的运算。p=a;/*指针指针p指向了数组指向了数组a的首地址的首地址*/1)p+/*使使p指向下一个元素指向下一个元素*/2)*p+*(p+)/*先得到先得到*p的值,指针的值,指针p指向下一地址指向下一地址*/如:如:for(i=0;i5;i+,p+)printf(“%d”,*p);3)*(p+)与与*(+p)不同不同可改为:可改为:for(i=0;i5;i+)printf(“%d”,*p+);244)+(*p)/*p指向的值加指向的值加1*
21、/若若pa0,a0=5,则则+(*p)a0=65)若)若pai,则:,则:*(p-)ai-/*先做先做*p运算,运算,p再自减再自减*/*(-p)a-i/*先做先做p自减,再做自减,再做*运算运算*/*(+p)a+i同理同理256)指针的关系运算 若两个指针指向同一个数组的元素,则可以进行关系运算,运算结果为0或1。、=、=:判断两个指针指向的数据位置的前后关系=,!=:判断两个指针是否指向同一个数据7)指针变量可以有空值,即该指针变量不指向任何变量。p=NULL;p=NULL;2610.3.3用数组名作函数参数用数组名作函数参数数组名作数组名作实参实参时:起始地址时:起始地址形参数组形参数组
22、;数组名作数组名作形参形参时:接收实参数组的起始地址时:接收实参数组的起始地址实际上,实际上,c编译是把形参数组名作为指针变量来处理。编译是把形参数组名作为指针变量来处理。如:如:f(inta,intn)f(int*a,intn)等价等价27例例10.7请把数组请把数组a中的中的n个元素按相反的顺序存放。个元素按相反的顺序存放。1234567891010 987654321算法:算法:a0an-1a1an-2aint(n-1)/2an-int(n-1)/2)-1设循环变量设循环变量i,ji=0;j=n-1aiaj交换交换;直到;直到i=(n-1)/2。i:0(n-1)/2(n-1):j-28m
23、ain()inti,a10=3,5,2,6,8,9,0,1,7,4;for(i=0;i10;i+)printf(%d,ai);printf(n);inv(a,10);/*数组名数组名a作实参作实参*/for(i=0;i10;i+)printf(%d“,ai);程序:程序:voidinv(intx,intn)/*数组名数组名x作形参作形参*/inttemp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;voidinv(int*x,intn)/*指针变量指针变量x作形参作形参*/inttemp,*i,*j,*p,m=(n-1)
24、/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;指针变量能否作形参?指针变量能否作形参?/*ia0,ja9,pa4*/29总结:总结:数组及指向数组的指针变量作函数参数时,数组及指向数组的指针变量作函数参数时,可有种等价形式可有种等价形式P238-239(本质上是一种,即指针(本质上是一种,即指针数据作函数参数)数据作函数参数):(1)形参、实参都用数组名)形参、实参都用数组名(2)形参、实参都用指针变量)形参、实参都用指针变量(3)形参用指针变量,实参用数组名)形参用指针变量,实参用数组名(4)形参用数组名,实参用指针变量)
25、形参用数组名,实参用指针变量3010.3.4指向多维数组的指针指向多维数组的指针1.多维数组元素的地址多维数组元素的地址2.inta34=1,3,5,7,9,11,13,15,17,19,21,231357911131517192123a0a1a2aa数组包括数组包括3个元素:个元素:a0a1a2,而每个元素又是一个一维数组。,而每个元素又是一个一维数组。因此:因此:aa0第第0行行&a00a+1a1第第1行行&a10a+2a2第第2行行&a20可看作:可看作:2000a+12008a+220161=8个字节个字节31分析:第分析:第0 0行行1 1列列的的地址地址表示表示?(&a01)(&a
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 10 谭浩强

限制150内