c语言基础教程第七章指针

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第七章指针7.1.1什么是指针指针是一种特殊的变量。它的特殊性表现在哪些地方呢?由于指针是一种变量,它就应该具有变量的三要素:名字、类型和值。于是指针的特殊性就应表现在这兰个要素上。指针的名字与一般变量的规定相同,没有什么特殊的地方。指针的值是某个变量的地址值。因此我们说指针是用来存放某个变量地址值的变量。指针的值与一般变量的值是不同的,这是指针一个特点。这就是说,指针是用来存放某个变量的地址值的,当然被存放地址值的那个变量是已经定义过的,并且被分配了确定的内存地址值的。一个指针存放了哪个变量的地址值,就说该指针指向那个变量。指针的第二个特点就表现在它的类型上,指针的类型是该指针所指向的变量的类型,而不是指针本身值的类型,因为指针本身值是内存的地址值,其类型自然是int型或lang型。而指针的类型是由它所指向的变量的类型决定。由于指针可以指向任何一种类型的变量C语言中所允许的变量类型〕,因此,指针的类型是很多的,例如,int型,char型,float型、数组类型、结构类型、联合类型,还可以指向函数、文件和指针等。下面通过一个例子,进一步对指针的两个特点加深理解。例如,inta=5,*P;这里,说明了变量a是int型的,并且赋了初值。在说明语句中,}P表示P是一个指针,括号(,)是说明符,它说明后面的变量不是一般变量,而是指针,并且P是一个int型指针,意味着P所指向的变量是一个int型变量。假定,要指针P指向变量a,由于指针是用来存放变量的地址值的,因此,要将变量a的地址贼给指针P,变量a的地址表示为肠,这里邑是运算符,表示取其后面变量的地址值。如果有p=&a;则P是指向变量a的指针。假定a被分配的内存地址是3000h,P和a的关系如下图所示:图中标明变量a的内存地址为30O0,变量P的内存地址为3500H,变量a的值(即内容)为5,而指针P的值为3000H,可见指针P是用来存放变量a的地址值的。C语言中关于地址值的表示有如下规定:(1)一般变量的地址值用变量名前加运算符&表示。例如,变量x的地址值为&x等。(2)数组的地址值可用数组名表示,数组名表示该数组的首元素的地址值。数值中某个元素的地址值用&,运算符加上数组元素名。例如:inta[10],*p1,*p2;P1=a;p2=&a[5];这里,*p1和*p2是指向int型变量的指针,pl=a;表示指针P1指向a数组的首元素;P2=&a[5];表示指针p2指向数组a的数组元素a[5]的指针。(3)函数的地址值用该函数的函数名来表示,指向函数的指针可用它所指向的函数名来赋值。(4)结构变量的指针用尽运算符加结构变量名来表示,结构变量的成员的地址也用邑运算符加结构变量的成员名来表示。关于结构变量和结构变量的成员将在结构一章中讲解。关于&运算符的用法需要注意的是它可以作用在一般变量名前、数组元素名前、结构变量名前和结构成员名前等,而不能作用在数组名前,也不能作用在表达式前和常量前。综上所述,对指针的含意应作如下理解:指针是一种不同于一般变量的特殊变量,它是用来存放某个变量的地址值的,它存放哪个变量的地址就称它是指向那个变量的指针。指针的类型不是它本身值的类型,而是它所指向的变量的类型。简单地说,对指针应记住如下两点:(1)指针的值是地址值。(2)指针的类型是它的所指向变量的类型。7.1.2指针的表示在明确了指针的含意以后,接着要学会正确地表示指针。它在表示上也有差别。应记住各种不同类型指针的表示。(1)指向基本类型变量的指针表示如下:①指向int型变量的指针。例如:int*pI,p2;这里,P1和p2是两个指向整型变量的指针,p1和p2前的*是表示指针的说明符。②指向。har型变量的指针,例如:char*pcl,*pc2;这里,pcl和pc2是两个指向字符型变量的指针。③指向float型变量的指针,例如:float*pf1,*pf2,double*pdl,pd2;这里,pfl和pf2是两个指向单精度浮点型变量的指针。pdl和pd2是两个指向双精度浮点型变量的指针。(2)指向数组的指针表示如下:①一般地,认为指向数组的指针就是指向该数组首元素的指针,例如:inta[5][3],(*pa)[3];其中,a是一个二维数组的数组名,pa是一个指向数组的指针名。pa是一个指向每列有3个元素的二维数组的指针。例如,Pa=a;则表示指针pa指向二维数组a指向数组的指针的表示与指针数组的表示很相似,使用时要注意其区别。例如:floatm[3][2],,*P1[3],(*p2)[2];这里,m是一个二维数组名,p1是一个一维一级指针数组名。所谓指针数组就是数组的元素为指针的数组。P1是指针数组名,数组p1有3个元素,每个元素是一个一级指针,该指针指向float型变量,p2是一个指向数组的指针,它指向一个每列有2个元素的二维数组。可见,p1和p2的表示形式很相似,前者是指针数组,后者是指向数组的指针,其含意是完全不同的。{②指向数组元素的指针一般是指向该数组的任何一个元素。例如;floatn[10][5],*p;p=&n[5][1];这里,P是一个指向float型变量的指针,将数组n的某个元素的地址值,如&n[5][1]赋给该指针P,则P便是一个指向数组n的某个元素的指针。一般地,指向数组元素的指针是一个指向该数组元素所具有的类型的变量的指针,它与指向数组的指针在表示上是有区别的。(3)指向函数的指针表示如下:int(,pf)();这里,pf是一个指向函数的指针,它所指向的函数的返回值为int型数。指向函数的指针与指针函数在表示_L要区别开口下面的pf是一个指针函数:int*pf();这里,pf是一个返回值为int型数的指针函数。所谓指针函数是一种返回值为指针的函数。(4)指向指针的指针表示如下:int**pp;这里,PP是一个指向指针的指针,即是一个二级指针。所谓二级指针是指它所存放的地址是一个一级指针的地址值,即它所指向的是一个一级指针。所以,二级指针又称为指针的指针。同样,三级指级所存放的是一个二级指针的地址值,该二级指针又存放着一级指针的地址值,该一级指针才存放某个变量的地址值。所以,三级指针是指针的指针的指针。依此类推。关于结构变量的指针和文件指针以后再讲解。7.1.3指针的赋值前面已经讲过,指今十的值是地址值,因此,给指针赋值或赋初值要是一个地址值亡各种变量的地址值的表示方法前面已经讲过了。所以给指针赋值不是一件困难的事情。1.赋值和赋初值给指针可以赋值,也可以赋初值。赋值是用一个赋值表达式语句进行;赋初值是在说明或定义指针的同时给它赋值。不论是赋值还是赋初值,对一般的指针都是给予一个相对应的地址值;对于指针数组,则按其数组的赋值或赋初值方法进行赋值。例如:intx,*p=&.x;这是给指向int型变量指针P赋初值,即将int型变量二的地址值赋给了P.如果写成赋值的方式,如下所示:intx,*P;p=&x;又例如,floaty[2][3]*PY[2]={Y[0],Y[1]};这是给一个指针数组PY赋初值,PY是一个具有2个元素的指针数组,它的每个元素是一个float型的指针,这里Y[0]和y[1]是用来表示二维数组y的两个行地址,即将数组Y看成是三行三列的一个数组,每一行是一个一维数组,它由3个元素组成。由此可见,一个二维数组可以表示为一个一维的指针数组,该指针数组的每个元素对应二维数组的每一行。上例又可写成赋值的形式,如下所示:floaty[2][3],*PY[2];PY[0]=y[0]PY[1]=y[l];或者,intifloaty[2][3],*PY[2];for(i=0;i2;i++)PY[i]=u[i];对于一个指间函数的指针,可用函数名给它赋值。例如:doublesin(),(*Pf)();pl=sin;这里,p1是一个指向函数的指针,将一个函数名sin赋给了P1,则p1便是一个指向函数sin的指针。对于指向数组的指针,一般用相应的数组名给它赋值(或赋初值).例如:intx[3][5],(*px)[5];Px一x;这里,px是一个指肉数组的指针名,它所指向的数组是一个具有每列5个元素的二维数组。将数组X的数组名赋给px,则Px将指向二维数组X。对于指向数组元素的指针,就将它所指向的某个数组元素的地址值斌给它。在对多级指针赋值时,要注意所赋予的指针的级别要与所赋给的地址值相对应。这就是说,给一个一级指针赋值,则用一个变量的地址值就可以了;给一个二级指针赋值,则要用某个变量的地址的地址值,依次类推。关于其他类型指针的赋值或赋初值后面还会讲到。给指针斌值还有一种常用的方法,这就是使用存储管理函数malloc(),该函数的格式如下:(void*)malloc(size)Intsize;该函数是用来分配内存地址的。该函数有一个参数size,用来表示所申请内存大小的字节数。该函数所分配的内存地址值,可用来存放所指定的任何类型变量的地址值。该函数如果成功地分配了内存地址,则返回一个地址值。否则,返回NULL(即。地址),表示申请分配内存失败。例如:Char*s;S=(char*)malloc(10*sizeof(char))其中,s是一个char型指针,它可以用来存放一个字符串。通过调用系统提供的malloc()函数,申请10*sizeaf(char)个字节的内存空间,如果申请成功,:将获得一个地址,该地址值是内存中某个空间的首地址值。如果s的值为NULL,这说明申请失败,s没有获得内存空间。又例如:Int*pa;Pa=(int*)malloc(sizeof(int)pa是一个指向int型变量的指针,使用malloc()函数将获得一个内存地址值,于是p:便是一个被赋了地址值的指针。在实际应用中,常用malloc()函数给指针赋值,读者一定要掌握这种方法。2.指针斌值时应注意的事项给指针赋值(或赋初值)除了要用地址值外,还要注意下面几点。(1)指针被定义后,只有赋了值(或赋了初值)才能使用。或者说,没有被斌值的指针不能使用。使用没有被赋值的指针是很危险的,有可能造成系统的瘫痪。道理是很简单的。因为一个没有被赋值的指针,定义后它将被分配一个内存空间,该空间仍保存着原来的内容,即存在一个无效的地址值,该地址值可能是内存中存放关健系统软件的地址,一且使用了该指针去改变了它所指向的内容,则会造成系统软件被改变,因此有可能造成系统的瘫痪。所以,一定要记住,指针在使用前一定要先赋值。(2)给指针赋值时一定要注意类型的一致。这就是说,ant型变量指针要赋一个i}t型变量的地址值,或用malloc()函数赋值时,前面要强制int型指针类型。例如:Inta,*pa;Pa=&a;或者,Pa=(int*)malloc(sizeof(int))都是正确的,而下列赋值是错误的Int*paFloatbPa=&b或者pa=(int*)malloc(sizeof(float))(3)可将一个已赋值的指针值赋给另一个同类型的指针。这里,有两点要注意:一个已赋值的指针,而没有被赋值的指针不能赋给另一个指针;二是同类型的指针,而不同类型的指针是不能这徉赋值的。例如:Inta,*p,*qP=&aq=p这里,先给指针p赋值,然后再将指针P赋给同类型的指针q,于是指针q和p同时指向变量a.(4)暂时不用的指针可以赋值NULL.例如:int*p;p=NULL;其中,P是一个暂时不用的指针被赋值为NULL.前面讲过,指针不赋值就使用是很危险的。因此,为了避免这种危险,可将暂时不用的指针赋值VULL,将来使用时再重新赋值。这样,被赋值为NULL的指针一旦被使用也不会带来危险。被赋值为NULL的指针又称为无效指针。(5)指针也可以被赋一个整型数值,但是使用这种赋值的方法要十分慎重。一般对于内存的地址分配情况不是十分清楚的人,请一定不要作这种冒险的事情。因为这种赋值方法,也会带来系统瘫痪的危险。7.1.4指针所指向变的值指针的值,前面已经讨论过了,它是所指向变量的地址值。而指针所指向变量的值就是该指针所存放地址的那个变量的值

1 / 48
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功