欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    C“指针”学习建议.pdf

    • 资源ID:90896070       资源大小:6.63MB        全文页数:55页
    • 资源格式: PDF        下载积分:12金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要12金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    C“指针”学习建议.pdf

    C+“指针”学习建议一.对于众多人提出的C/C+中指针难学的问题做个总结:指针学习不好关键是概念不清造成的,说的简单点就是书没有认真看,指针的学习犹如人在学习饶口令不多看多学多练是不行的,下面是两个很经典的例子,很多书上都有,对于学习的重点在于理解*x和 x 的理解,他们并不相同,*x 所表示的其实就是变量a 本身,x 表示的是变量a 在内存中的地址,如果想明白可以输出观察cout<<*x|x;,当定义了 int*x;后对x=&a的理解的问题。仔细阅读和联系下面的两个例子我想指针问题就不是难点了!#include<stdio.h>main()(inta,b;/*定义a,b两个整形变量用于输入两个整数*/int*point_l,*point_2,*temp_point;/*定义三个指针变量*/scanf(%d,%d,&a,&b);/*格式化输入 a,b 的值*/point_l=&a;/*把指针变量point_l的值指向变量a 的地址*/point_2=&b;/*把指针变量point_2的值指向变量b 的地址*/if(a<b)(temp_point=point_l;/*这里的 temp_point 是用于临时存储point_l的值也就是变量a 的地址的*/point_l=point_2;/*把 point_2 的值赋予 point_l*/poi nt_2=tem p_poi nt;/*由于point_l的值已经改变无法找至1 J,利用前面临时存储的也就是 temp_point找回原point_l的值赋予point_2,打到把point_l和point_2值对换的目的*/printf(%d,%cT,*point_l,*point_2);/*利用*point 和*point_2 也就是分辨指向b 和 a 的方法把值显示屏幕上*/)/*此题需要注意和了解是的此法并没有改变变量a,b的值只是利用指针变量分别存储a 和 b 的地址,然后再把那两个指针变量的值对换一下其实就是存储在指针变量里面a 与 b 的地址对换,在利用*point_l和*point_2的方式把调换后的值显示出来这里的*point 实际就是a,此中算法并非真的改变a,b的值,而是利用指针进行地址交换达到大小排序的目的.*/#include<stdio.h>main()(inta,b;/*定义a,b两个整形变量用于输入两个整数*/int*point_l,*point_2;/*定义三个指针变量*/scanf(%d,%d,&a,&b);/*格式化输入 a,b 的值*/point_l=&a;/*把指针变量point_l的值指向变量a 的地址*/point_2=&b;/*把指针变量point_2的值指向变量b 的地址*/compositor(pointJL,point_2);/*调用自定义的排序涵数,把a,b的地址传递给 point_l 和 point_2*/printf(%d,%cT,a,b);/*打印出 a,b 的值*/staticcompositor(pl,p2)int*pl,*p2;/*定义形式参数pl,p2为指针变量*/(inttemp;/*建立临时存储变量*/if(*pl<*p2)/*如果*pl<p2,注意这里的*p l和*p2其实就是a和 b*/(temp=*pl;/*利用变量temp用于临时存储*p l和就是a 的值*/*pl=*p2;/*将*p l的值也就是a 的值换成*p2的值也就是b 的值,等价于a=b*/*p2=temp;/*将*p2的值也就是temp的值等价于b=temp*/)/*注意:此题与上题不同的是,直接改变了 a 于 b 的值达到真实改变的目的*/二.C+指针使用方法解惑/voidClearList(LNode*&HL)w仔细看一下这种声明方式,确实有点让人迷惑。下面以 voidfuncl(MYCLASS*&pBuildingElement);为例来说明这个问题。在某种意义上,*和&是意思相对的两个东西,把它们放在一起有什么意义呢?。为了理解指针的这种做法,我们先复习一下C/C+编程中无所不在的指针概念。我们都知道MYCLASS*的意思:指向某个对象的指针,此对象的类型为MYCLASS。Voidfunci(MYCLASS*pMyClass);例如:MYCLASS*p=newMYCLASS;fund(p);上面这段代码的这种处理方法想必谁都用过,创建一个MYCLASS对象,然后将它传入funcl函数。现在假设此函数要修改pMyClass:voidfunci(MYCLASS*pMyClass)(DoSomething(pMyClass);pMyClass=其它对象的指针第二条语句在函数过程中只修改了 pMyClass的值。并没有修改调用者的变量P 的值。如果p 指向某个位于地址0 x008a00的对象,当fund返回时,它仍然指向这个特定的对象。(除非funcl有 bug将堆弄乱了,完全有这种可能。)现在假设你想要在funcl中修改p 的值。这是你的权利。调用者传入一个指针,然后函数给这个指针赋值。以往一般都是传双指针,即指针的指针,例如,CMyClass*oMYCLASS*p=NULL;fund(&p);voidfunci(MYCLASS*pMyClass);(*pMyClass=newMYCLASS;调用funcl之后,p指向新的对象。在COM编程中,你到处都会碰到这样的用法-例如在查询对象接口的Queryinterface 函数中:interfacelSomelnterfaceH RESULTQuery Interface(IID&iid,void*ppvObj);LPSOMEINTERFACEp=NULL;pOb->Querylnterface(IID_SOM曰NTERFACE,&p);此处,p是SOMEINTERFACE类型的指针,所以&p便是指针的指针,在Query Interface返回的时候,如果调用成功,则变量p包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:voidfunci(MYCLASS*&pMyClass);pMyClass=newMYCLASS;其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p本身:MYCLASS*p=NULL;fund(p);在调用之后,p指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么场合要使用这种方法,我会说,极少。MFC在其集合类中用到了它一例如,CQbList,它是一个Cobjects指针列表。ClassCObList:publicCobject获取/修改指定位置的元素Cobject*&GetAt(POSITIONposition);Cobject*GetAt(POSITIONposition)const;这里有两个GetAt函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:Cobject*pObj=mylist.GetAt(pos);则 pObj是列表中某个对象的指针,如果接着改变pObj的值:pObj=pSomeOtherObj;这并改变不了在位置pos处的对象地址,而仅仅是改变了变量pObjo 但是,如果你写成下面这样:Cobject*&rpObj=mylist.GetAt(pos);现在,rpObj是引用一个列表中的对象的指针,所以当改变rpObj时,也会改变列表中位置pos处的对象地址-换句话说,替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在 C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C+高手,对引用的概念没有透彻的理解和熟练的应用是不行的。三.数据指针在 C/C+语言中一直是很受宠的;几乎找不到一个不使用指针的C/C+应用。用于存储数据和程序的地址,这是指针的基本功能。用于指向整型数,用整数指针(int*);指向浮点数用浮点数指针(float*);指向结构,用对应的结构指针(structxxx*);指向任意地址,用无类型指针(void*)。有时候,我们需要一些通用的指针。在 C 语言当中,(void*)可以代表一切;但是在C+中,我们还有一些比较特殊的指针,无法用(void*)来表示。事实上,在 C+中,想找到一个通用的指针,特别是通用的函数指针简直是一个“不可能任务二C+是一种静态类型的语言,类型安全在C+中举足轻重。在 C语言中,你可以用void*来指向一切;但在C+中,void*并不能指向一切,就算能,也失去了类型安全的意义了。类型安全往往能帮我们找出程序中潜在的一些BUGo下面我们来探讨一下,C+中如何存储各种类型数据的指针。C+指针探讨(一,)数据指针沐枫网志L 数据指针数据指针分为两种:常规数据指针和成员数据指针1.1 常规数据指针这个不用说明了,和 C 语言一样,定义、赋值是很简单明了的。常见的有:int*,double*等等。如:intvalue=123;int*pn=&value;1.2 成员数据指针有如下的结构:structMyStruct(intkey;intvalue;现在有一个结构对象:MyStructme;MyStruct*pMe=&me;我们需要value成员的地址,我们可以:int*pValue=&me.value;或int*pValue=&pMe->value;当然了,这个指针仍然是属于第一种范筹-常规数据指针。好了,我们现在需要一种指针,它指向MyStruct中的任一数据成员,那么它应该是这样的子:intMyStruct:*pMV=&MyStruct:value;或intMyStruct:*pMK=&MyStruct:key;这种指针的用途是用于取得结构成员在结构内的地址。我们可以通过该指针来访问成员数据:intvalue=pMe->*pMV;取得pM e的value成员数据。intkey=me.*pMK;取得 me 的 key 成员数据。那么,在什么场合下会使用到成员数据指针呢?确实,成员指针本来就不是一种很常用的指针。不过,在某些时候还是很有用处的。我们先来看看下面的一个函数:intsum(MyStruct*objs/intMyStruct:*pm,intcount)intresult=O;for(inti=0;i<count;+i)result+=objsi.*pm;returnresult;这个函数的功能是什么,你能看明白吗?它的功能就是,给定count个MyStruct结构的指针,计算出给定成员数据的总和。有点拗口对吧?看看下面的程序,你也许就明白了:MyStructme10=(1,2,3,4,5,6,亿 8,9,10,11,12,13,14,15,16,17,18,19,20;intsum_value=sum(me/&MyStruct:value/10);计算10个MyStruct结构的value成员的总和:sum_value值为110intsum_key=sum(me/&MyStruct:key/10);计算10个MyStruct结构的key成员的总和:sum_key值为100(2+4+6+8+20)(1+3+5+7+19)也许,你觉得用常规指针也可以做到,而且更易懂。0 k,没问题:intsum(MyStruct*objs,intcount)(intresult=O;for(inti=0;i<count;+i)result+=objsi.value;returnresult;你是想这么做吗?但这么做,你只能计算value,如果要算key的话,你要多写一个函数。有多少个成员需要计算的话,你就要写多少个函数,多麻烦啊。指针四.C+指针使用在下列函数声明中,为什么要同时使用*和&符号?以及什么场合使用这种声明方式?voidfuncl(MYCLASS*&pBuildingElement);论坛中经常有人问到这样的问题。本文试图通过一些实际的指针使用经验来解释这个问题。仔细看一下这种声明方式,确实有点让人迷惑。在某种意义上,”和&是意思相对的两个东西,把它们放在一起有什么意义呢?。为了理解指针的这种做法,我们先复习一下C/C+编程中无所不在的指针概念。我们都知道MYCLASS*的意思:指向某个对象的指针,此对象的类型为 MYCLASSo voidfuncl(MYCLASS*pMyClass);例如:MYCLASS*p=newMYCLASS;funcl(p);上面这段代码的这种处理方法想必谁都用过,创建一个MYCLASS对象,然后将它传入funcl函数。现在假设此函数要修改pMyClass:voidfuncl(MYCLASS*pMyClass)DoSomething(pMyClass);pMyClass=其它对象的指针第二条语句在函数过程中只修改了 pMyClass的值。并没有修改调用者的变量p的值。如果p指向某个位于地址0 x008a00的对象,当funci返回时,它仍然指向这个特定的对象。(除非funcl有bug将堆弄乱了,完全有这种可能。)现在假设你想要在fu n cl中修改p的值。这是你的权利。调用者传入一个指针,然后函数给这个指针赋值。以往一般都是传双指针,即指针的指针,例如,CMyClass*o MYCLASS*p=NULL;funcl(&p);voidfuncl(MYCLASS*pMyClass);(*pMyClass=newMYCLASS;)调用fu n cl之后,p指向新的对象。在COM编程中,你到处都会碰到这样的用法-例如在查询对象接口的Queryinterface函数中:interfacelSomelnterfaceHRESULTQuerylnterface(IID&iid,void*ppvObj);LPSOMEINTERFACEp=NULL;pOb->Querylnterface(IID_SOMEINTERFACE/&p);此处,p是SOM日INTERFACE类型的指针,所以&p便是指针的指针,在Queryinterface返回的时候,如果调用成功,则变量p包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:voidfuncl(MYCLASS*&pMyClass);(pMyClass=newMYCLASS;其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p本身:MYCLASS*p=NULL;funcl(p);在调用之后,P指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么场合要使用这种方法,我会说,极少。MFC在其集合类中用到了它-例如,CObList,它是一个CObjects指针列表。classCObList:publicCObject获取/修改指定位置的元素CObject*&GetAt(POSITIONposition);CObject*GetAt(POSITIONposition)const;;这里有两个GetAt函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:CObject*pObj=mylist.GetAt(pos);则 pObj是列表中某个对象的指针,如果接着改变pObj的值:pObj=pSomeOtherObj;这并改变不了在位置pos处的对象地址,而仅仅是改变了变量pObjo但是,如果你写成下面这样:CObject*&rpObj=mylist.GetAt(pos);现在,rpObj是引用一个列表中的对象的指针,所以当改变rpObj时 一,也会改变列表中位置pos处的对象地址-换句话说,替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C+高手,对引用的概念没有透彻的理解和熟练的应用是不行的。五.新手学习之浅析C/C+中的指针在学习c/c+过程中,指针是一个比较让人头痛的问题,稍微不注意将会是程序编译无法通过,甚至造成死机。在程序设计过程中,指针也往往是产生隐含bug的原因。下面就来谈谈指针的应用以及需要注意的一些问题,里面也许就有你平时没有注意到的问题,希望能帮助各位读者理解好指针。一、我们先来回忆一下指针的概念吧,方便下面的介绍指针是存放地址值的变量或者常量。例如:inta=l;&a就表示指针常量(“&”表示取地址运算符,也即引用)。int*b,b表示的是指针变量(注意,是b表示指针变量而不是*b),*表示要说明的是指针变量。大家注意int*b2和int(*b)是不同的,int是表示一个指针数组,而int(*b)表示含有两个元素的int指针,这里要注意运算优先级问题,有助于理解指针问题。在这里大概介绍基本概念就够了,至于具体使用方法,如赋值等,很多书都有介绍,我就不多说了。二、应用以及注意的问题1、理解指针的关键所在对指针类型和指针所指向的类型的理解、指针类型:可以把指针名字去掉,剩下的就是这个指针例如:int*a;指针类型为int*int*a;指针类型为int*int*(*a)8;指针类型为 int*(*)8、指针所指向的类型:是指编译器将把那一片内存所看待成的类型。这里只要把指针声明语句中的指针名字和名字右边的“*”号去掉就可以了,剩下的就是指针所指向的类型。我之所以把他们放在第一位,是因为弄清楚他们是学C/C+指针的重点,正确理解他们才能使你打好C/C+的编程基础。2、指针的应用传递参数。其实它可以相当于隐式的返回值,这就比return的方法更加灵活了,可以返回更多的值,看看下面的例子自然就明白了:#includeiostream.hvoidexample(int*al,int&bl,intcl)(*al*=3;+bl;+cl;voidmain()(int*a;intb,c;*a=6;b=7;c=10;example(a,b,c);cout<<*a=<<*a<cout<<b=<cout<<c=<输出:*a=18b=8c=10注意到没有,*a和 b 的值都改变了,而 c 没有变。这是由于al是指向*a(=6)的指针,也即与a 是指向同一个地址,所以当a l指向的值改变了,*a的值也就改变了。在函数中的参数使用了引用(int&bl),b l是 b 的别名,也可以把它当作特殊的指针来理解,所以b 的值会改变。函数中的参数 intel只是在函数中起作用,当函数结束时候便消失了,所以在main()中不起作用。3、关于全局变量和局部变量的一个问题先不废话了,先看看程序:#include,/iostream.h/inta=5;int*examplel(intb)a+=b;return&a;int*example2(intb)(intc=5;b+=c;return&b;voidmain()(int*al=examplel(10);int*bl=example2(10);cout<<wal=w<<*al<cout<<wbl=w<<*bl<)输出结果:al=15bl=4135*b l怎么会是4135,而不是15呢?是程序的问题?没错吧?由于a 是全局变量,存放在全局变量的内存区,它一直是存在的;而局部变量则是存在于函数的栈区,当函数example2()调用结束后便消失,是b指向了一个不确定的区域,产生指针悬挂。下面是对examplel()和exam pl e2()的反汇编(用TC+3.0编译):examplel():pushbp;入栈movbp;spmovax,bp+04;传递参数addOOAA,ax;相 力 口movaxQOAA;返回了结果所在的地址popbp;恢复栈,出栈ret;退出函数example2():pushbp;入栈movbp,spsubsp,02movwordptrbp-02z0005movax,bp-02;传递参数addbp+04,ax;相加leaax,bp+04;问题就出在这里movsp,bppopbp;恢复栈,出栈ret;退出函数对比之后看出来了吧?ax应该是存储的是结果的地址。而在example?()中,返回的却是 bp+04 的内容,因此指针指向了一个不确定的地方,由此产生的指针悬挂。examplel()中,ax返回了正确的结果的地址。4、内存问题:使用指针注意内存的分配和边界。使用指针过程中应该给变量一个适当的空间,以免产生不可见的错误。请看以下代码:#include,/iostream.h/voidmain()(char*al;char*a2;cin>>al;cin>>a2;cout<<wal=/7<cout<<wa2=w<输入:abc123输出:al=123a2=Nullpointerassignment指针指向了“空二解决办法就是分配适当的内存给这两个字符串。修正后的代码如下:#include/iostream.hwvoidmain()(char*al;char*a2;al=newchar10;a2=newchar10;cin>>al;cin>>a2;cout<<wal=w<cout<<,a2=/<delete(a 1);注意,别忘了要释放内存空间delete(a2);到此就能输出正确的结果了。分配了适当的内存之后要注意释放内参空间,同时还应该注意不要超出所分配的内存的大小,否则会有溢出现象产生,导致不可预料的结果。5、关于特殊的指针引用引用有时候应用起来要比指针要灵活,用它做返回的时候是不产生任何变量的副本的这样减小了内存的占用,提高执行的速度。引用使用起来要比指针好理解,比较直观。当引用作为参数时,不会改变参数的地址,因此可以作为左值。下面请看一个例子:#include/iostream.h/,charch5=ABCD;char&example(intb)(returnch;voidmain()(cout<<ch=<example(2)=wcw;cout<<wch=/?<输出结果:ch=ABCDch=ABcD在实际编程过程中,可以灵活地引用或指针,尽量提高程序的可读性和执行效率。三、小结:指针是学习C/C+的重点难点,主要原因是指针较为抽象,不容易理解。使用指针千万要明白让指针指向什么地方,如何让指针指向正确的地方。在深入系统底层之中需要应用到大量的指针,因此需要理解好指针的基本概念,例如:指针类型和指针所指向的类型。平时应该对留心观察,了解程序的工作过程,必要时候可以对程序进行反汇编,加深对指针的理解,这种方法同样适合学别的编程方面的知识。四、结束:指针的应用是很广泛的,利用指针可以做很多事情,要成为一个好的程序员,必须对指针有比较深刻的了解。写本文的目的在于让大家对指针有更深一层的了解,提高指针的应用能力,内容大都是我在实际编程中遇到的问题。相信能给大家一定的帮助。六.C+中关于指针入门的最好的文章什么是指针?其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据。这是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表。开始学习如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名字前加上一个星号。我们来看一个例子:下面这个程序定义了两个指针,它们都是指向整型数据。int*pNumberOne;int*pNumberTwo;你注意到在两个变量名前的“P”前缀了吗?这是程序员通常在定义指针时的一个习惯,以提高便程序的阅读性,表示这是个指针。现在让我们来初始化这两个指针:pNumberOne=&some_number;pNumberTwo=&some_other_number;&号 读 作“什么的地址”,它表示返回的是变量在内存中的地址而不是变量本身的值。在这个例子中,pNumberOne等于some_number 的地址,所以现在 pNumberOne 指向 some_numbero如果现在我们在程序中要用到some_number,我们就可以使用pNumberOneo我们来学习一个例子:在这个例子中你将学到很多,如果你对指针的概念一点都不了解,我建议你多看儿遍这个例子,指针是个很复杂的东西,但你会很快掌握它的。这个例子用以增强你对上面所介绍内容的了解。它是用C编写的(注:原英文版是用C写的代码,译者重新用C+改写写了所有代码,并 在DEVC+和VC+中编译通过!)#include<iostream.h>voidmain()声明变量:intnNumber;int*pPointer;现在给它们赋值:nNumber=15;pPointer=&nNumber;打印出变量nNumber的值:cout<<nNumberisequalto:<<nNumber<<endl;现在通过指针改变nNumber的值:*pPointer=25;证明nNumber已经被上面的程序改变重新打印出nNumber的值:cout<<nNumberisequalto:<<nNumber<<endl;通读一下这个程序,编译并运行它,务必明白它是怎样工作的。如果你完成了,准备好,开始下一小节。陷井!试一下,你能找出下面这段程序的错误吗?#include<iostream.h>int*pPointer;voidSomeFunction();intnNumber;nNumber=25;让指针指向nNumber:pPointer=&nN umber;voidmain()(SomeFunction();为 pPointer 赋值为什么这里失败了?为什么没有得到25cout<<Valueof*pPointer:<<*pPointer<<endl;这段程序先调用了 SomeFunction函数,创建了个叫nNumber的变量,接着让指针pPointer指向了它。可是问题出在哪儿呢?当函数结束后,nNumber被删掉了,因为这一个局部变量。局部变量在定义它的函数执行完后都会被系统自动删掉。也就是说当SomeFunction函数返回主函数main()时,这个变量已经被删掉,但pPointer还指着变量曾经用过的但现在已不属于这个程序的区域。如果你还不明白,你可以再读读这个程序,注意它的局部变量和全局变量,这些概念都非常重要。但这个问题怎么解决呢?答案是动态分配技术。注意这在C和C+中是不同的。由于大多数程序员都是用C+,所以我用到的是C+中常用的称谓。动态分配动态分配是指针的关键技术。它是用来在不必定义变量的情况下分配内存和让指针去指向它们。尽管这么说可能会让你迷惑,其实它真的很简单。下面的代码就是一个为一个整型数据分配内存的例子:int*pNumber;pNumber=newint;第一行声明一个指针pNumber。第二行为一个整型数据分配一个内存空间,并 让pNumber指向这个新内存空间。下面是一个新例,这一次是用double双精型:double*pDouble;pDouble=newdouble;这种格式是一个规则,这样写你是不会错的。但动态分配又和前面的例子有什么不同呢?就是在函数返回或执行完毕时,你分配的这块内存区域是不会被删除的所以我们现在可以用动态分配重写上面的程序:#include<iostream.h>int*pPointer;voidSomeFunction()让指针指向一个新的整型pPointer=newint;*pPointer=25;voidmain()(SomeFunction();为 pPointer 赋值cout<<Valueof*pPointer:<<*pPointer<<endl;通读这个程序,编译并运行它,务必理解它是怎样工作的。当SomeFunction调用时,它分配了一个内存,并 让pPointer指向它。这一次,当函数返回时,新的内存区域被保留下来,所 以pPointer始终指着有用的信息,这是因为了动态分配。但是你再仔细读读上面这个程序,虽然它得到了正确结果,可仍有一个严重的错误。分配了内存,别忘了回收太复杂了,怎么会还有严重的错误!其实要改正并不难。问题是:你动态地分配了一个内存空间,可它绝不会被自动删除。也就是说,这块内存空间会一直存在,直到你告诉电脑你已经使用完了。可结果是,你并没有告诉电脑你已不再需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致系统崩溃。所以这是很重要的,在你用完它以后,请释放它的空间,如:deletepPointer;这样就差不多了,你不得不小心。在这你终止了一个有效的指针(一个确实指向某个内存的指针)。下面的程序,它不会浪费任何的内存:#include<iostream.h>int*pPointer;voidSomeFunction()让指针指向一个新的整型pPointer=newint;*pPointer=25;voidmain()(SomeFunction();为 pPointer 赋值cout<<Valueof*pPointer:<<*pPointer<<endl;deletepPointer;只有一行与前一个程序不同,但就是这最后一行十分地重要。如果你不删除它,你就会制造一起“内存漏洞”,而让内存逐渐地泄漏。(译者:假如在程序中调用了两次SomeFunction,你又该如何修改这个程序呢?请读者自己思考)传递指针到函数传递指针到函数是非常有用的,也很容易掌握。如果我们写一个程序,让一个数加上5,看一看这个程序完整吗?:#include<iostream.h>voidAddFive(intNumber)(Number=Number+5;voidmain()(intnMyNumber=18;cout<<Myoriginalnumberis<<nMyNumber<<endl;AddFive(nMyNumber);cout<<Mynewnumberis<<nMyNumber<<endl;问题出在函数AddFive里用到的Number是变量nMyNumber的一个副本而传递给函数,而不是变量本身。因此,Number=Number+5这一行是把变量的副本加了 5,而原始的变量在主函数main()里依然没变。试着运行这个程序,得到了结果23吗?问题出在哪儿?自己去体会一下。要解决这个问题,我们就要传递一个指针到函数,所以我们要修改一下函数让它能接受指针:把'voidAddFive(intNumberj'改成'voidAddFive(int*Number)'o 下面就是改过的程序,注意函数调用时要用&号,以表示传递的是指针:#include<iostream.h>voidAddFive(int*N umber)(*Number=*Number+5;voidmain()(intnMyNumber=18;cout七.我眼中的指针-学习指针不可少的好文章我眼中的指针-学习指针不可少的好文章为初学者服务。这是我的帖子的宗旨。我也是个初学者(强调了无数遍了),我以我的理解把初学者觉得难懂的东西用浅显的语言写出来。由于小学时语文没学好,所以竭尽全力也未必能达到这个目的。尽力而为吧。指针是c和C+中的难点和重点。我只精通dos下 的basiCo c语言的其它各种特性,在basic中都有类似的东西。只有指针,是baisc所不具备的。指针是c的灵魂。我不想重复大多数书上说得很清楚的东西,我只是把我看过的书中说得不清楚或没有说,而我又觉得我理解得有点道理的东西写出来。我的目的是:l o通过写这些东西,把我脑袋中关于c的模糊的知识清晰化。2 o 给初学者们一点提示。3 o 赚儿个经验值。(因为贴这些东西没有灌水之嫌啊)第一章。指针的概念指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。先声明儿个指针放着做例子:例一:(l)int*ptr;(2)char*ptr;(3)int*ptr;(4)int(*ptr)3;(5)int*(*ptr)4;如果看不懂后儿个例子的话,请参阅我前段时间贴出的文?如何理解c 和 C+的复杂类型声明>>。l o 指针的类型。从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:int*ptr;指针的类型是int*(2)char*ptr;指针的类型是char*int*ptr;指针的类型是int*int(*ptr)3;指针的类型是int(*)(5)int*(*ptr)4;指针的类型是 int*(*)4怎么样?找出指针的类型的方法是不是很简单?2 o 指针所指向的类型。当你通过指针来访问指针所指向的内存区时、指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:int*ptr;指针所指向的类型是int(2)char*ptr;指针所指向的的类型是char(3)int*ptr;指针所指向的的类型是int*int(*ptr)3;指针所指向的的类型是int()int*(*ptr);指针所指向的的类型是int*()4在指针的算术运算中,指针所指向的类型有很大的作用。指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C 越来越熟悉时,你会发现,把与指针搅和在一起的 类型 这个概念分成 指针的类型 和 指针所指向的类型 两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指

    注意事项

    本文(C“指针”学习建议.pdf)为本站会员(无***)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开