C“指针”学习建议.pdf
《C“指针”学习建议.pdf》由会员分享,可在线阅读,更多相关《C“指针”学习建议.pdf(55页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+“指针”学习建议一.对于众多人提出的C/C+中指针难学的问题做个总结:指针学习不好关键是概念不清造成的,说的简单点就是书没有认真看,指针的学习犹如人在学习饶口令不多看多学多练是不行的,下面是两个很经典的例子,很多书上都有,对于学习的重点在于理解*x和 x 的理解,他们并不相同,*x 所表示的其实就是变量a 本身,x 表示的是变量a 在内存中的地址,如果想明白可以输出观察cout<<*x|x;,当定义了 int*x;后对x=&a的理解的问题。仔细阅读和联系下面的两个例子我想指针问题就不是难点了!#include<stdio.h>main()(inta,b;/*
2、定义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 的值赋
3、予 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 的地址对换,
4、在利用*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的值指向
5、变量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
6、的值换成*p2的值也就是b 的值,等价于a=b*/*p2=temp;/*将*p2的值也就是temp的值等价于b=temp*/)/*注意:此题与上题不同的是,直接改变了 a 于 b 的值达到真实改变的目的*/二.C+指针使用方法解惑/voidClearList(LNode*&HL)w仔细看一下这种声明方式,确实有点让人迷惑。下面以 voidfuncl(MYCLASS*&pBuildingElement);为例来说明这个问题。在某种意义上,*和&是意思相对的两个东西,把它们放在一起有什么意义呢?。为了理解指针的这种做法,我们先复习一下C/C+编程中无所不在的指针概念。我们都
7、知道MYCLASS*的意思:指向某个对象的指针,此对象的类型为MYCLASS。Voidfunci(MYCLASS*pMyClass);例如:MYCLASS*p=newMYCLASS;fund(p);上面这段代码的这种处理方法想必谁都用过,创建一个MYCLASS对象,然后将它传入funcl函数。现在假设此函数要修改pMyClass:voidfunci(MYCLASS*pMyClass)(DoSomething(pMyClass);pMyClass=其它对象的指针第二条语句在函数过程中只修改了 pMyClass的值。并没有修改调用者的变量P 的值。如果p 指向某个位于地址0 x008a00的对象,
8、当fund返回时,它仍然指向这个特定的对象。(除非funcl有 bug将堆弄乱了,完全有这种可能。)现在假设你想要在funcl中修改p 的值。这是你的权利。调用者传入一个指针,然后函数给这个指针赋值。以往一般都是传双指针,即指针的指针,例如,CMyClass*oMYCLASS*p=NULL;fund(&p);voidfunci(MYCLASS*pMyClass);(*pMyClass=newMYCLASS;调用funcl之后,p指向新的对象。在COM编程中,你到处都会碰到这样的用法-例如在查询对象接口的Queryinterface 函数中:interfacelSomelnterface
9、H RESULTQuery Interface(IID&iid,void*ppvObj);LPSOMEINTERFACEp=NULL;pOb->Querylnterface(IID_SOM曰NTERFACE,&p);此处,p是SOMEINTERFACE类型的指针,所以&p便是指针的指针,在Query Interface返回的时候,如果调用成功,则变量p包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:voidfunci(MYCLASS*&pMyClass);pMyClass=newM
10、YCLASS;其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p本身:MYCLASS*p=NULL;fund(p);在调用之后,p指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么场合要使用这种方法,我会说,极少。MFC在其集合类中用到了它一例如,CQbList,它是一个Cobjects指针列表。ClassCObList:publicC
11、object获取/修改指定位置的元素Cobject*&GetAt(POSITIONposition);Cobject*GetAt(POSITIONposition)const;这里有两个GetAt函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:Cobject*pObj=mylist.GetAt(pos);则 pObj是列表中某个对象的指针,如果接着改变pObj的值:pObj=pSomeOtherObj;这并改变不了在位置pos处的对象地址,而仅仅是改变了变量pObjo 但是,如果你写成下面这样:Cobject*&am
12、p;rpObj=mylist.GetAt(pos);现在,rpObj是引用一个列表中的对象的指针,所以当改变rpObj时,也会改变列表中位置pos处的对象地址-换句话说,替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在 C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C+高手,对引用的概念没有透彻的理解和熟练的应用是不行的。三.数据指针在 C/C+语言中一直是很受宠的;几乎找不到一个不使用指针的C/C+应用。用于存储数
13、据和程序的地址,这是指针的基本功能。用于指向整型数,用整数指针(int*);指向浮点数用浮点数指针(float*);指向结构,用对应的结构指针(structxxx*);指向任意地址,用无类型指针(void*)。有时候,我们需要一些通用的指针。在 C 语言当中,(void*)可以代表一切;但是在C+中,我们还有一些比较特殊的指针,无法用(void*)来表示。事实上,在 C+中,想找到一个通用的指针,特别是通用的函数指针简直是一个“不可能任务二C+是一种静态类型的语言,类型安全在C+中举足轻重。在 C语言中,你可以用void*来指向一切;但在C+中,void*并不能指向一切,就算能,也失去了类型安
14、全的意义了。类型安全往往能帮我们找出程序中潜在的一些BUGo下面我们来探讨一下,C+中如何存储各种类型数据的指针。C+指针探讨(一,)数据指针沐枫网志L 数据指针数据指针分为两种:常规数据指针和成员数据指针1.1 常规数据指针这个不用说明了,和 C 语言一样,定义、赋值是很简单明了的。常见的有:int*,double*等等。如:intvalue=123;int*pn=&value;1.2 成员数据指针有如下的结构:structMyStruct(intkey;intvalue;现在有一个结构对象:MyStructme;MyStruct*pMe=&me;我们需要value成员的地址
15、,我们可以: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
16、;取得 me 的 key 成员数据。那么,在什么场合下会使用到成员数据指针呢?确实,成员指针本来就不是一种很常用的指针。不过,在某些时候还是很有用处的。我们先来看看下面的一个函数:intsum(MyStruct*objs/intMyStruct:*pm,intcount)intresult=O;for(inti=0;i<count;+i)result+=objsi.*pm;returnresult;这个函数的功能是什么,你能看明白吗?它的功能就是,给定count个MyStruct结构的指针,计算出给定成员数据的总和。有点拗口对吧?看看下面的程序,你也许就明白了:MyStructme10=
17、(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)(
18、intresult=O;for(inti=0;i<count;+i)result+=objsi.value;returnresult;你是想这么做吗?但这么做,你只能计算value,如果要算key的话,你要多写一个函数。有多少个成员需要计算的话,你就要写多少个函数,多麻烦啊。指针四.C+指针使用在下列函数声明中,为什么要同时使用*和&符号?以及什么场合使用这种声明方式?voidfuncl(MYCLASS*&pBuildingElement);论坛中经常有人问到这样的问题。本文试图通过一些实际的指针使用经验来解释这个问题。仔细看一下这种声明方式,确实有点让人迷惑。在某种意义
19、上,”和&是意思相对的两个东西,把它们放在一起有什么意义呢?。为了理解指针的这种做法,我们先复习一下C/C+编程中无所不在的指针概念。我们都知道MYCLASS*的意思:指向某个对象的指针,此对象的类型为 MYCLASSo voidfuncl(MYCLASS*pMyClass);例如:MYCLASS*p=newMYCLASS;funcl(p);上面这段代码的这种处理方法想必谁都用过,创建一个MYCLASS对象,然后将它传入funcl函数。现在假设此函数要修改pMyClass:voidfuncl(MYCLASS*pMyClass)DoSomething(pMyClass);pMyClass
20、=其它对象的指针第二条语句在函数过程中只修改了 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
21、指向新的对象。在COM编程中,你到处都会碰到这样的用法-例如在查询对象接口的Queryinterface函数中:interfacelSomelnterfaceHRESULTQuerylnterface(IID&iid,void*ppvObj);LPSOMEINTERFACEp=NULL;pOb->Querylnterface(IID_SOMEINTERFACE/&p);此处,p是SOM日INTERFACE类型的指针,所以&p便是指针的指针,在Queryinterface返回的时候,如果调用成功,则变量p包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就
22、理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:voidfuncl(MYCLASS*&pMyClass);(pMyClass=newMYCLASS;其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p本身:MYCLASS*p=NULL;funcl(p);在调用之后,P指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么
23、场合要使用这种方法,我会说,极少。MFC在其集合类中用到了它-例如,CObList,它是一个CObjects指针列表。classCObList:publicCObject获取/修改指定位置的元素CObject*&GetAt(POSITIONposition);CObject*GetAt(POSITIONposition)const;;这里有两个GetAt函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:CObject*pObj=mylist.GetAt(pos);则 pObj是列表中某个对象的指针,如果接着改变pObj
24、的值:pObj=pSomeOtherObj;这并改变不了在位置pos处的对象地址,而仅仅是改变了变量pObjo但是,如果你写成下面这样:CObject*&rpObj=mylist.GetAt(pos);现在,rpObj是引用一个列表中的对象的指针,所以当改变rpObj时 一,也会改变列表中位置pos处的对象地址-换句话说,替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成
25、为C/C+高手,对引用的概念没有透彻的理解和熟练的应用是不行的。五.新手学习之浅析C/C+中的指针在学习c/c+过程中,指针是一个比较让人头痛的问题,稍微不注意将会是程序编译无法通过,甚至造成死机。在程序设计过程中,指针也往往是产生隐含bug的原因。下面就来谈谈指针的应用以及需要注意的一些问题,里面也许就有你平时没有注意到的问题,希望能帮助各位读者理解好指针。一、我们先来回忆一下指针的概念吧,方便下面的介绍指针是存放地址值的变量或者常量。例如:inta=l;&a就表示指针常量(“&”表示取地址运算符,也即引用)。int*b,b表示的是指针变量(注意,是b表示指针变量而不是*b)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 指针 学习 建议
限制150内