下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 10_第10章 指针

10_第10章 指针.ppt

10_第10章 指针

tianxingmeizhou
2010-12-15 0人阅读 举报 0 0 暂无简介

简介:本文档为《10_第10章 指针ppt》,可适用于工程科技领域

第十章指针第十章指针地址和指针的概念数据在内存的存放、读取方式(以变量为例):用户在程序设计中定义一个变量内存区每一个字节有一个编号地址编译过程中:、根据变量类型分配一定长度的内存空间、变量名转换为所分配内存的地址、用户存取数据方式变量名地址地址所标志的内存段、数据使用前的编译处理过程数据*一个比方:旅客变量数据旅客名字变量名旅馆房间内存区旅馆房间号地址查找旅客:旅客名字房间号码房间找到旅客存取数据:变量名内存地址内存区数据*注意:内存单元的地址与内存单元的内容是不同的。内存单元地址旅馆房间号码内存单元内容住在房间内的旅客。内存地址内存用户数据区内存中存放的数据、数据存取举例设程序中已定义三个整型变量i,j,k编译时系统将和两个字节给变量i、给j、给k。内存分配示意图如下内存地址内存用户数据区printf(“d”,i)变量名i地址取变量值送到PRNk=ij变量名i地址取变量值变量名j地址取变量值相加得送到K占用的,、直接访问与间接访问直接访问:在数据存取中直接得到变量i地址然后按变量i的地址存取变量i的值的方式。间接访问:在数据存放中变量i的地址不是直接得到而是存放在另一个变量ipointer中须先从变量ipointer中获取变量i地址然后按变量i地址存取变量值i的方式。*一个比方(取抽屉A中的东西):直接访问:直接得到钥匙A打开抽屉A取出东西(直接获得变量i地址按变量i地址存取变量的i值)间接访问:钥匙A在抽屉B中用钥匙B打开抽屉B得到钥匙A打开抽屉A取得东西变量i地址放在变量ipointer中读取变量ipointer值得到变量i的地址按变量i地址存取i值*间接访问例子过程:根据变量名ipointer获得地址到地址读取数据得到(变量i的地址)到地址读取数据得到变量i的值。内存地址内存用户数据区、指针和指针变量指针:一个变量的在内存区中的地址称为指针。通过变量的指针可以找到变量的存储单元从而读取其中存放的值指针变量:专门用来存放指针的变量称为指针变量。指针变量存放的数据为另一变量的地址(指针)。注意:指针与指针变量的区别指针是一个地址用于指向存放变量数据的内存单元指针变量是一个变量它的值是指针例如:变量i的地址为该变量的指针变量ipointer是用来存放变量i的指针的它是一个指针变量。变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量指针:它首先是一个地址是指变量在内存中的地址指针变量:它是一个变量是一个专门存放变量地址的变量用来指向另一个变量。为了表示指针变量和它所指向的变量之间的联系在程序中用“*”表示“指向”例:ipointer代表指针变量而*ipointer是ipointer所指向的变量。如下图所示:ipointer*ipointeri*ipointer与i是等效的都表示同一变量该变量存放地址为。因此:①i=②*ipointer=两语句作用相同定义一个指针变量定义一个指针变量例:inti,jint*pointer,*pointer第一条命令定义了两个整型变量i,j第二条命令定义了①两个指针变量pointerpointer它们指向整型变量②两个整型变量*pointer*pointer它们与ij为相同类型被pointerpointer两个指针所指向*基类型:指针变量的基类型是指该指针变量可以指向的变量的类型定义指针变量的一般形式:基类型*指针变量名例:float*pointer(pointer是指向实型变量的指针变量)char*pointer(pointer是指向字符型变量的指针变量)指针变量指向的改变:方法:将一个该指针允许指向的变量的地址赋给该指针pointer=ipointeripointeri执行赋值语句之前执行赋值语句之后定义指针变量时应注意的两点:()“*”表明它后面所跟的变量类型是指针型变量需要指出的指针变量名为pointer而不是*pointer*pointer是一个整型变量()在定义指针变量时必须指定基类型。因为不同数据类型占用的内存空间大小不同在进行指针移动和运算时将导致不同的结果。如“指针值+”对于基类型为整型将向后移动两个字节对于基类型为实型将向后移动四个字节指针变量的引用指针变量的引用WARNING:指针变量中只能存放地址(指针)不能把其它类型的数据赋给指针变量。例:pointer为指针变量pointer=为非法赋值因为为整型变量。有关的两个运算符:():取地址运算符()*:指针运算符(或称为“间接访问”运算符)例:a为变量a的地址*p为指针变量p所指向的存储单元二指针变量的引用例main(){inta,bint*p,*pa=b=p=ap=bprintf(“d,dn”,a,b)*“直接访问”方式*printf(“d,dn”,*p,*p)*“间接访问”方式*}结果:,,程序中:*p表示指针变量p所指向的变量,即a*p表示指针变量p所指向的变量,即bpaabpb*p*p关于与*运算符的说明::是取地址运算符如:a,b等*是指针运算符用于定义时表示其后的标识符是指针变量而在程序中*p则表示指针变量p所指向的变量,即目标变量。,*,,––同优先级,按从右至左方向结合a:如:inta,*p,*pp=a则:*p与a等效如:p=*p或p=a则:p也指向变量ab:如:inta,*pp=a则:*a与*p等效,即等价于变量ac:如:inta,*pp=a则:(*p)等价于a但注意*p不等价于(*p)ap*p*aa因为*p等价于*(p)即先得p所指向变量的值,再使指针变量p的值自增,此时p已不在指向原来的变量了例voidmain(){int*p,*p,*p,a,bscanf(“d,d”,a,b)p=ap=bif(a<b){p=pp=pp=p}(进行地址交换)printf(“a=d,b=dn”,a,b)printf(“max=d,min=dn”,*p,*p)}如输入:,输出:a=,b=max=,min=(注意:本程序是采用交换指针变量p和p的指向来实现两个数的比较的且比较前后a,b的值并未发生变化)abbappppppabab三指针变量作为函数的参数指针变量可以作函数的参数,其作用是将一个变量的地址传送到另一个函数中。例voidswap(int*p,int*p){intpp=*p*p=*p*p=p}voidmain(){inta,b,*pointer,*pointerscanf(“d,d”,a,b)pointer=apointer=bif(a<b)swap(pointer,pointer)printf(“nd,dn”,a,b)}若输入:,输出为:,本程序采用的是交换a和b的值,而p和p的值不变同例相反如果把swap函数改成:swap(p,p){int*p,*pint*p*p=*p(此句有问题)*p=*p*p=*p}又如:swap(intx,inty){inttt=xx=yy=t}P无确定的地址值它的的值不可预见*p所指向的单元也是不可预见对*p赋值可能会破坏系统的正常状态。注意参数的传递类型为“值传递”说明:不能通过改变形参指针变量的值而使实参指针变量的值改变可以通过改变形参指针变量所指向的变量的值来改变实参指针变量所指向的变量的值如想通过函数调用得到n个要改变的值,可以:()在主调函数中设n个变量,并用n个指针变量指向它们()将指针变量作实参,使n个变量的地址传给所调用的函数形参()通过形参指针变量,改变该n个变量的值()主调函数中就可以使用这些改变了值的变量。swap(int*p,int*p){int*pp=pp=pp=p}main(){inta,b,*pointer,*pointerscanf(“d,d”,a,b)pointer=apointer=bif(a<b)swap(pointer,pointer)printf(“nd,dn”,a,b)}本函数中试图通过改变形参指针变量的值来使实参指针变量的值改变作者原意图是实现这样的结果C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式指针变量作为函数参数也要遵循这一规律总结:总结:要实现变量值的双向传递在被调函数中必须对指针变量所指向的目标变量进行操作。如果只是对指针变量本身进行操作仍然是单向传递。这点是指针变量作为函数参数的难点和重点。例输入a,b,c个整数按大小顺序输出swap(int*pt,int*pt){intpp=*pt*pt=*pt*pt=p}exchange(int*q,*q,*q){if(*q<*q)swap(q,q)if(*q<*q)swap(q,q)if(*q<*q)swap(q,q)}main(){inta,b,c,*p,*p,*pscanf(“d,d,d”,a,b,c)p=ap=bp=cexchange(p,p,p)printf(“nd,d,dn”,a,b,c)}§数组的指针和指向数组的指针变量§数组的指针和指向数组的指针变量C语言中指针变量可以指向变量也可以指向数组和数组元素数组的指针:数组的起始地址数组元素的指针:数组元素的地址一指向数组的指针变量的定义与赋值指向数组的指针变量的定义同指向变量的指针变量的定义相同如:intaint*p若:p=a则p指向了a数组的第号元素由于数组名代表数组的首地址(即起始地址)故:p=a等价于p=a也可:intaint*p=aint*p=a注意int*p=a的含义是将数组首地址赋给指针变量p,而不是赋给(*p)二通过指针引用数组元素如:inta,*pp=a则:()pa的地址pa的地址……piai的地址()*p==a,*(p)==a,……*(pi)==ai说明:数组元素在内存中是连续存放的,C语言规定,指针变量p指向下一个元素(不是简单的加)(pi)表示指向ai的地址,而ai也表示ai的地址,故程序中(pi)等价于ai如:pa指向数组的指针变量可以带下标如:pi*(pi)a数组pp,api,aip,aaaaia*(pi)综上所述:数组元素的引用可以:(假定:inta,*p=a)()下标法:数组名下标或指针变量名下标aipi()指针法:*(pi)或*(ai)例用二种方法输出数组各元素()下标法main(){inta,ifor(i=i<i)scanf(“d”,ai)printf(“n”)for(i=i<i)printf(“d”,ai)}()用数组名计算元素地址main(){inta,ifor(i=i<i)scanf(“d”,ai)printf(“n”)for(i=i<i)printf(“d”,*(ai))}注意几点:注意几点:()指针变量可以作自增,自减运算如:p,p––而数组名不能作自增,自减运算如a,––a等,均不合法因为数组名是常量()注意指针变量的当前值如:例:main(){inta,i,*pp=afor(i=i<i)scanf(“d”,p)printf(“n”)for(i=i<i,p)printf(“d”,*p)}()注意指针变量的运算如:inta,i,*pp=a则:ap(或p=)表示p指向a,此时若执行*p,则取出a元素的值b“*”与“”同优先级,自右往左结合如:*p等效于*(p),即先取p所指向变量的值,再使p而*(p)与*(p)的作用不同前者先取*p的值,后使p后者是先使p,再取*p的值(*p)表示使目标变量的值加而不是指针变量的值加。e*(p)等价于ai*(p)等价于ai即先使p自增,再作*运算如:main(){inta,*pp=awhile(p<a)printf(“d”,*p)}main(){inta,*pp=awhile(p<a){printf(“d”,*p)p}}三数组名作函数参数三数组名作函数参数数组名作函数参数时,实际上是将实参数组的首地址传给形参。这样实参数组与形参数组共占同一段内存。使得在调用函数过程中形参数组中元素值发生变化也就使实参数组的元素值随之而发生变化。如:main(){intarray……f(array,)……}f(arr,n)intarr,n{……}arr)实参传递给形参后arr和array指向同一内存地址)将“”传递给形参n后界定了形参数组的范围)这种“数组名+数组元素个数”的参数形式是常用的。例将数组a中n个整数按相反顺序存放题意分析:本题的关键是最后交换的两个元素的上下标值的确定。即将第一个元素和最后一个元素对换,将第二个同倒数第二个对换……即两两对换,直到:aint(n–)与an–int((n–))对换为止。voidinv(intx,intn){intt,i,j,m=(n–)for(i=i<=mi){j=n––it=xixi=xjxj=t}return}main(){staticinti,a={,,,,,,,,,}printf(“Theoriginalarray:n”)for(i=i<i)printf(“d”,ai)printf(“n”)inv(a,)printf(“Thearrayhasbeeninverted:n”)for(i=i<i)printf(“d”,ai)printf(“n”)}例从个数中找出其中最大值和最小值intmax,minvoidmaxminvalue(intarray,intn){int*p,*arrayendarrayend=arraynmax=min=*arrayfor(p=arrayp<arrayendp)if(*p>max)max=*pelseif(*p<min)min=*p}main(){inti,numberprintf(“enterdatan”)for(i=i<i)scanf(“d”,numberi)maxminvalue(number,)printf(“nmax=d,min=dn”,max,min)}此例也可改用指针变量来传送地址,程序可改为:intmax,minvoidmaxminvalue(int*array,intn){int*p,*arrayendarrayend=arraynmax=min=*arrayfor(p=arrayp<arrayendp)if(*p>max)max=*pelseif(*p<min)min=*preturn}main(){inti,number,*pp=numberprintf(“enterdatan”)for(i=i<i,p)scanf(“d”,p)printf(“thedata:n”)for(p=number,i=i<i,p)printf(“d”,*p)p=numbermaxminvalue(p,)printf(“nmax=d,min=dn”,max,min)}for(p=numberp<(number)p)等效于:综上所述,对于实参数组,想在被调函数中改变此数组元素的值,实参与形参的对应关系可以如下:综上所述,对于实参数组,想在被调函数中改变此数组元素的值,实参与形参的对应关系可以如下:()二者都用数组名main(){inta……f(a,)……}f(intx,intn){……}特点:a和x数组共用同一段内存单元。()实参为数组名,形参用指针变量main(){inta……f(a,)……}f(int*x,intn){……}特点:实参将数组的首地址传给形参指针变量,通过指针变量指向数组中的任一元素,进而作相应的处理。()二者都用指针变量。main(){inta,*pp=a……f(p,)……}f(int*x,intn){……}特点:先使p指向a数组,再将p传给x,使x也指向a数组,从而进行处理()实参为指针变量,而形参为数组名。main(){inta,*pp=a……f(p,)……}f(intx,intn){……}特点:利用指针变量将a数组的首地址传给x数组使两数组共用同一段内存单元利用xi值的变化,使ai的值也发生变化注意:在上述四种处理方式中,当用指针变量作实参时必须先使指针变量有确定的值即指向一个已定义的数组。四、指针与二维数组四、指针与二维数组、指针与二维数组一个数组的名字代表该数组的首地址并可看成是地址常量这一规定对二维数组或更高维数组同样适用。若有定义:float*p,d则:二维数组元素和二维数组元素的地址二维数组元素和二维数组元素的地址假设数组名为a起始地址设为inta={{,,,},{,,,},{,,,}}则:a代表整个二维数组的首地址即第行的首地址a是数组a第行首地址()a,a,a是二维数组中三个一维数组的名字(地址)是第行第行第行的首地址即:a=a、a=a、a=aaij是第i行j列的地址*(aij)是该地址存储的值即aij考虑*(a)=注意:注意:ai和*(ai)无条件等价ai、ai、*(ai)、ai均表示第i行首地址aij、aij、*(ai)j都是第i行j列元素的地址aij、*(aij)、*(*(ai)j)都是第i行j列元素的值◆二维数组名(如a)是指向行的一维数组名(如a,a)是指向列元素的。在指向行的指针前面加上一个*就转换成为指向列的指针。反之在指向列的指针前面加就成为指向行的指针。、指向多维数组元素的指针指向多维数组元素的指针形式有种:()指向数组元素的指针变量。这种方式跟指向变量的指针变量的使用方法一样。这里主要要掌握的是:aij在数组中相对位置的计算公式i*mj从这个公式可以看到C语言规定数组的下标从开始对计算上述相对位置比较方便只要知道了i和j的值就可以用公式计算出aij相对于数组开头的相对位置。()指向由m个元素组成的一维数组的指针变量。定义格式:基类型(*指针变量名)常量表达式例如:int(*p)(与inta比较)表示*p有个元素每个元素为整数也就是p所指向的对象是有个整型元素的数组。假设:p开始指向的地址为那么:p=?、用指向数组的指针作为函数参数在用指针变量作形参以接受实参数组名传递来的地址时有两种方法:()用指向变量的指针变量作为形参。()用指向一维数组的指针变量作为形参。例有一个班个学生各学门课计算总平均分数以及第n个学生的成绩。程序如下:#include<stdioh>voidmain(){voidaverage(float*p,intn)voidsearch(float(*p),intn)floatscore={{,,,},{,,,},{,,,}}average(*score,)search(score,)}voidaverage(float*p,intn){float*pendfloatsum=,averpend=pnfor(p<=pendp)sum=sum(*p)aver=sumnprintf("average=fn",aver)}voidsearch(float(*p),intn){intiprintf("thescoreofNodare:n",n)for(i=i<i)printf("f",*(*(pn)i))}例:将a矩阵与b矩阵相加,和存入c矩阵。例:将a矩阵与b矩阵相加,和存入c矩阵。inti,jmain(){int*p,a,b,cprintf("Thevalueofa:n")for(i=i<i)for(j=j<j)scanf("d",aij)printf("Thevalueofb:n")for(i=i<i)for(j=j<j)scanf("d",*(bi)j)matrix(*a,b,c)printf("Thevalueofc:")for(i=,p=cp<cp,i){if(i==)printf("n")printf("d",*p)}}matrix(int*x,int*y,int*z){for(i=i<i)for(j=j<j)*(zi*j)=*(xi*j)*(yi*j)}数组元素在内存中按“行优先”的顺序存放因此可用xi*j表示二维数组各元素的地址§字符串的指针和指向字符串的指针变量§字符串的指针和指向字符串的指针变量字符串的指针就是字符串的首地址一字符串的表示形式:用字符数组实现例main(){staticcharstring=“ILoveChina”printf(“sn”,string)}例中string是数组名,它表示字符数组的首地址。相应的streingi表示数组中的一个元素如:string代表第五个元素即字母v。用字符指针实现例main(){char*string=“ILoveChina”printf(“sn”,string)}例中string是一个指向字符串的指针变量。尽管程序中没有直接定义字符型数组,但实际上,C语言对字符串常量均按字符数组来处理即在内存中开辟了一个字符数组用来存放字符串常量另外,char*string=“ILoveChina”等价于以下两条语句:char*stringstring=“ILoveChina”其含义是将字符串的首地址赋给指针变量string。注意:C语言中对字符串可以进行整体输入和输出而对数值型数组则不能用数组名来输出它的全部元素,只能逐个元素输出如:inta……printf(“dn”,a)(不行)对字符串的处理可以用下标法也可用指针法对字符串的处理可以用下标法也可用指针法例将字符串a复制到字符串bmain(){chara=“Iamaboy”,bfor(i=*(ai)!=‘’i)*(bi)=*(ai)*(bi)=‘’printf(“stringais:sn”,a)printf(“stringbis:”)for(i=bi!=‘’i)printf(“c”,bi)printf(“n”)}运行结果:stringais:Iamaboystringbis:Iamaboy例用指针变量来处理例问题main(){chara=“Iamaboy”,b,*p,*pintip=ap=bfor(*p!=‘’p,p)*p=*p*p=‘’printf(“stringais:sn”,a)printf(“stringbis:”)for(i=bi!=‘’i)printf(“c”,bi)printf(“n”)}二字符串指针作函数参数二字符串指针作函数参数用字符数组名和指向字符串的指针变量作函数参数,均可以处理字符串。例用函数调用实现字符串的复制()用字符数组作函数参数voidcopystring(charfrom,charto){inti=while(fromi!=‘’)(先判断,后赋值){toi=fromii}toi=‘’}main(){chara=“Iamateacher”charb=“youareastudent”printf(“stringa=snstringb=sn”,a,b)copystring(a,b)printf(“nstringa=snstringb=sn”,a,b)}本程序main函数中也可用字符型指针变量改写如下:main(){char*a=“Iamateacher”char*b=“youareastudent”printf(“stringa=snstringb=sn”,a,b)copystring(a,b)printf(“nstringa=snstringb=sn”,a,b)}()形参用字符指针变量voidcopystring(char*from,char*to){for(*from!=‘’from,to)*to=*from*to=‘’}main(){char*a=“Iamateacher”char*b=“youareastudent”printf(“stringa=snstringb=sn”,a,b)c

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/90

10_第10章 指针

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利