C++“指针”学习建议.pdf

上传人:索**** 文档编号:76242426 上传时间:2023-03-08 格式:PDF 页数:32 大小:167.20KB
返回 下载 相关 举报
C++“指针”学习建议.pdf_第1页
第1页 / 共32页
C++“指针”学习建议.pdf_第2页
第2页 / 共32页
点击查看更多>>
资源描述

《C++“指针”学习建议.pdf》由会员分享,可在线阅读,更多相关《C++“指针”学习建议.pdf(32页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、一.对于众多人提出的c/c+中指针难学的问题做个总结:指针学习不好关键是概念不清造成的,说的简单点就是书没有认真看,指针的学习犹如人在学习饶口令不多看多学多练是不行的,下面是两个很经典的例子,很多书上都有,对于学习的重点在于理解*x 和 x 的理解,他们并不相同,*x所表示的其实就是变量a 本身,x 表示的是变量 a在内存中的地址,如果想明白可以输出观察cout*x|x;,当定义了 int*x;后对 x=&a的理解的问题。仔细阅读和联系下面的两个例子我想指针问题就不是难点了!#include main()int a,b;/*定义 a,b 两个整形变量用于输入两个整数*/int *point_1

2、,*point_2,*temp_point;/*定义三个指针变量 */scanf(%d,%d,&a,&b);/*格式化输入 a,b 的值 */point_1=&a;/*把指针变量 point_1 的值指向变量a的地址 */point_2=&b;/*把指针变量 point_2 的值指向变量b的地址 */if (ab)temp_point=point_1;/*这里的 temp_point 是用于临时存储point_1 的值也就是变量a的地址的 */point_1=point_2;/*把 point_2 的值赋予 point_1*/point_2=temp_point;/*由于 point_1 的值

3、已经改变无法找到,利用前面临时存储的也就是temp_point 找回原 point_1 的值赋予 point_2,打到把 point_1 和 point_2 值对换的目的*/printf(%d,%d,*point_1,*point_2);/*利用*point_1 和*point_2也就是分辨指向b和 a 的方法把值显示屏幕上*/*此题需要注意和了解是的此法并没有改变变量a,b 的值只是利用指针变量分别存储a和 b 的地址,然后再把那两个指针变量的值对换一下其实就是存储在指针变量里面a与 b的地址对换,在利用*point_1 和*point_2的方式把调换后的值显示出来这里的*point_1 实

4、际就是 a,此中算法并非真的改变a,b 的值,而是利用指针进行地址交换达到大小排序的目的.*/#include main()int a,b;/*定义 a,b 两个整形变量用于输入两个整数*/int *point_1,*point_2;/*定义三个指针变量 */scanf(%d,%d,&a,&b);/*格式化输入 a,b 的值 */point_1=&a;/*把指针变量 point_1 的值指向变量 a 的地址*/point_2=&b;/*把指针变量 point_2 的值指向变量 b 的地址*/compositor(point_1,point_2);/*调用自定义的排序涵数,把 a,b 的地址传递

5、给point_1 和 point_2*/printf(%d,%d,a,b);/*打印出 a,b 的值*/static compositor(p1,p2)int *p1,*p2;/*定义形式参数p1,p2 为指针变量 */int temp;/*建立临时存储变量 */if (*p1*p2)/*如果*p1QueryInterface(IID_SOMEINTERFACE,&p);此处,p是 SOMEINTERFACE类型的指针,所以&p便是指针的指针,在QueryInterface返回的时候,如果调用成功,则变量 p包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完

6、全是一回事。如果你象下面这样声明函数:void func1(MYCLASS*&pMyClass);pMyClass=new MYCLASS;,其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p 本身:MYCLASS*p=NULL;func1(p);在调用之后,p 指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么场合要使用这种方法,我会说,极少。MFC 在其集

7、合类中用到了它-例如,CObList,它是一个 Cobjects指针列表。Class CObList:public Cobject ,/获取/修改指定位置的元素Cobject*&GetAt(POSITION position);Cobject*GetAt(POSITION position)const;这里有两个 GetAt 函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:Cobject*pObj=mylist.GetAt(pos);则 pObj 是列表中某个对象的指针,如果接着改变pObj 的值:pObj=pSomeOth

8、erObj;这并改变不了在位置pos 处的对象地址,而仅仅是改变了变量pObj。但是,如果你写成下面这样:Cobject*&rpObj=mylist.GetAt(pos);现在,rpObj 是引用一个列表中的对象的指针,所以当改变rpObj 时,也会改变列表中位置pos 处的对象地址-换句话说,替代了这个对象。这就是为什么 CObList 会有两个 GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在 C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C+高手,对引用的概念没有透彻

9、的理解和熟练的应用是不行的。三数据指针在 C/C+语言中一直是很受宠的;几乎找不到一个不使用指针的C/C+应用。用于存储数据和程序的地址,这是指针的基本功能。用于指向整型数,用整数指针(int*);指向浮点数用浮点数指针(float*);指向结构,用对应的结构指针(struct xxx*);指向任意地址,用无类型指针(void*)。有时候,我们需要一些通用的指针。在C语言当中,(void*)可以代表一切;但是在C+中,我们还有一些比较特殊的指针,无法用(void*)来表示。事实上,在 C+中,想找到一个通用的指针,特别是通用的函数指针简直是一个“不可能任务”。C+是一种静态类型的语言,类型安全

10、在C+中举足轻重。在C语言中,你可以用void*来指向一切;但在C+中,void*并不能指向一切,就算能,也失去了类型安全的意义了。类型安全往往能帮我们找出程序中潜在的一些BUG。下面我们来探讨一下,C+中如何存储各种类型数据的指针。C+指针探讨(一)数据指针沐枫网志 1.数据指针数据指针分为两种:常规数据指针和成员数据指针 1.1 常规数据指针这个不用说明了,和C语言一样,定义、赋值是很简单明了的。常见的有:int*,double*等等。如:int value=123;int *pn=&value;1.2 成员数据指针有如下的结构:struct MyStruct int key;int va

11、lue;现在有一个结构对象:MyStruct me;MyStruct*pMe=&me;我们需要 value 成员的地址,我们可以:int *pValue=&me.value;/或int *pValue =&pMe-value;当然了,这个指针仍然是属于第一种范筹-常规数据指针。好了,我们现在需要一种指针,它指向MyStruct 中的任一数据成员,那么它应该是这样的子:int MyStruct:*pMV=&MyStruct:value;/或int MyStruct:*pMK=&MyStruct:key;这种指针的用途是用于取得结构成员在结构内的地址。我们可以通过该指针来访问成员数据:int va

12、lue=pMe-*pMV;/取得 pMe的 value 成员数据。int key=me.*pMK;/取得 me的 key 成员数据。那么,在什么场合下会使用到成员数据指针呢?确实,成员指针本来就不是一种很常用的指针。不过,在某些时候还是很有用处的。我们先来看看下面的一个函数:int sum(MyStruct*objs,int MyStruct:*pm,int count)int result=0;for(int i=0;i count;+i)result+=objsi.*pm;return result;这个函数的功能是什么,你能看明白吗?它的功能就是,给定count 个 MyStruct 结

13、构的指针,计算出给定成员数据的总和。有点拗口对吧?看看下面的程序,你也许就明白了:MyStruct me10=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 ;int sum_value=sum(me,&MyStruct:value,10);/计算 10个 MyStruct 结构的 value 成员的总和:sum_value 值 为 110 (2+4+6+8+20)int sum_key=sum(me,&MyStruct:key,10);/计算 10个 MyStruct 结构的 key 成员的总和:sum_key 值 为 100 (1+3+

14、5+7+19)也许,你觉得用常规指针也可以做到,而且更易懂。Ok,没问题:int sum(MyStruct*objs,int count)int result=0;for(int i=0;i QueryInterface(IID_SOMEINTERFACE,&p);此处,p 是 SOMEINTERFACE类型的指针,所以&p便是指针的指针,在QueryInterface返回的时候,如果调用成功,则变量 p 包含一个指向新的接口的指针。如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:void func1(MYCLASS*&pMyClass);pMy

15、Class=new MYCLASS;,其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传 p 本身:MYCLASS*p=NULL;func1(p);在调用之后,p 指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到*。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。至于说什么场合要使用这种方法,我会说,极少。MFC 在其集合类中用到了它-例如,CObList,它是一个CObjects 指针列表。class CObList:

16、public CObject ,/获取/修改指定位置的元素CObject*&GetAt(POSITION position);CObject*GetAt(POSITION position)const;这里有两个 GetAt函数,功能都是获取给定位置的元素。区别何在呢?区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:CObject*pObj=mylist.GetAt(pos);则 pObj 是列表中某个对象的指针,如果接着改变pObj 的值:pObj=pSomeOtherObj;这并改变不了在位置pos 处的对象地址,而仅仅是改变了变量pObj。但是,如果你写成下面这样

17、:CObject*&rpObj=mylist.GetAt(pos);现在,rpObj 是引用一个列表中的对象的指针,所以当改变rpObj 时,也会改变列表中位置pos 处的对象地址-换句话说,替代了这个对象。这就是为什么CObList 会有两个 GetAt 函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。在 C/C+中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C+高手,对引用的概念没有透彻的理解和熟练的应用是不行的。五新手学习之浅析一下c/c+中的指针在学习 c/c+过程中,指针是一个比较让

18、人头痛的问题,稍微不注意将会是程序编译无法通过,甚至造成死机。在程序设计过程中,指针也往往是产生隐含bug 的原因。下面就来谈谈指针的应用以及需要注意的一些问题,里面也许就有你平时没有注意到的问题,希望能帮助各位读者理解好指针。一、我们先来回忆一下指针的概念吧,方便下面的介绍指针是存放地址值的变量或者常量。例如:int a=1;&a就表示指针常量(“&”表示取地址运算符,也即引用)。int*b,b表示的是指针变量(注意,是b表示指针变量而不是*b),*表示要说明的是指针变量。大家注意int*b2和 int(*b)2 是不同的,int*b 表示一个指针数组,而int(*b)2 表示含有两个元素的

19、int指针,这里要注意运算优先级问题,有助于理解指针问题。在这里大概介绍基本概念就够了,至于具体使用方法,如赋值等,很多书都有介绍,我就不多说了。二、应用以及注意的问题1、理解指针的关键所在对指针类型和指针所指向的类型的理解、指针类型:可以把指针名字去掉,剩下的就是这个指针例如:int*a;/指针类型为 int*int*a;/指针类型为int*int*(*a)8;/指针类型为 int*(*)8、指针所指向的类型:是指编译器将把那一片内存所看待成的类型。这里只要把指针声明语句中的指针名字和名字右边的“*”号去掉就可以了,剩下的就是指针所指向的类型。我之所以把他们放在第一位,是因为弄清楚他们是学c

20、/c+指针的重点,正确理解他们才能使你打好c/c+的编程基础。2、指针的应用传递参数。其实它可以相当于隐式的返回值,这就比return的方法更加灵活了,可以返回更多的值,看看下面的例子自然就明白了:#include iostream.h void example(int*a1,int&b1,int c1)*a1*=3;+b1;+c1;void main()int*a;int b,c;*a=6;b=7;c=10;example(a,b,c);cout*a=*a cout b=cout c=输出:*a=18 b=8 c=10 注意到没有,*a 和 b的值都改变了,而c 没有变。这是由于a1 是指向

21、*a(=6)的指针,也即与a是指向同一个地址,所以当 a1 指向的值改变了,*a 的值也就改变了。在函数中的参数使用了引用(int&b1),b1是 b的别名,也可以把它当作特殊的指针来理解,所以b的值会改变。函数中的参数int c1只是在函数中起作用,当函数结束时候便消失了,所以在main()中不起作用。3、关于全局变量和局部变量的一个问题先不废话了,先看看程序:#include“iostream.h”int a=5;int*example1(int b)a+=b;return&a;int*example2(int b)int c=5;b+=c;return&b;void main()int*

22、a1=example1(10);int*b1=example2(10);cout ”a1=”*a1 cout ”b1=”*b1a1;cin a2;cout ”a1=”cout ”a2=”a1;cin a2;cout ”a1=”cout ”a2=”delete(a1);注意,别忘了要释放内存空间delete(a2);到此就能输出正确的结果了。分配了适当的内存之后要注意释放内参空间,同时还应该注意不要超出所分配的内存的大小,否则会有溢出现象产生,导致不可预料的结果。5、关于特殊的指针引用引用有时候应用起来要比指针要灵活,用它做返回的时候是不产生任何变量的副本的这样减小了内存的占用,提高执行的速度。

23、引用使用起来要比指针好理解,比较直观。当引用作为参数时,不会改变参数的地址,因此可以作为左值。下面请看一个例子:#include“iostream.h”char ch5=”ABCD”;char&example(int b)return ch;void main()cout ”ch=”example(2)=”c”;cout”ch=”输出结果:ch=ABCD ch=ABcD 在实际编程过程中,可以灵活地引用或指针,尽量提高程序的可读性和执行效率。三、小结:指针是学习 c/c+的重点难点,主要原因是指针较为抽象,不容易理解。使用指针千万要明白让指针指向什么地方,如何让指针指向正确的地方。在深入系统底

24、层之中需要应用到大量的指针,因此需要理解好指针的基本概念,例如:指针类型和指针所指向的类型。平时应该对留心观察,了解程序的工作过程,必要时候可以对程序进行反汇编,加深对指针的理解,这种方法同样适合学别的编程方面的知识。四、结束:指针的应用是很广泛的,利用指针可以做很多事情,要成为一个好的程序员,必须对指针有比较深刻的了解。写本文的目的在于让大家对指针有更深一层的了解,提高指针的应用能力,内容大都是我在实际编程中遇到的问题。相信能给大家一定的帮助。六 C+中关于指针入门的最好的文章什么是指针?其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序

25、在内存的哪块区域可以找到数据。这是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表。开始学习如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名字前加上一个星号。我们来看一个例子:下面这个程序定义了两个指针,它们都是指向整型数据。int*pNumberOne;int*pNumberTwo;你注意到在两个变量名前的“p”前缀了吗?这是程序员通常在定义指针时的一个习惯,以提高便程序的阅读性,表示这是个指针。现在让我们来初始化这两个指针:pNumberOne=&some_number;pNumberTwo=&some_other_number;&号读作“什么的地址”,它

26、表示返回的是变量在内存中的地址而不是变量本身的值。在这个例子中,pNumberOne 等于 some_number 的地址,所以现在pNumberOne 指向 some_number。如果现在我们在程序中要用到some_number,我们就可以使用 pNumberOne。我们来学习一个例子:在这个例子中你将学到很多,如果你对指针的概念一点都不了解,我建议你多看几遍这个例子,指针是个很复杂的东西,但你会很快掌握它的。这个例子用以增强你对上面所介绍内容的了解。它是用C编写的(注:原英文版是用C写的代码,译者重新用C+改写写了所有代码,并在DEV C+和 VC+中编译通过!)#include voi

27、d main()/声明变量:int nNumber;int*pPointer;/现在给它们赋值:nNumber=15;pPointer=&nNumber;/打印出变量 nNumber的值:coutnNumber is equal to:nNumberendl;/现在通过指针改变nNumber的值:*pPointer=25;/证明 nNumber已经被上面的程序改变/重新打印出 nNumber的值:coutnNumber is equal to:nNumberendl;通读一下这个程序,编译并运行它,务必明白它是怎样工作的。如果你完成了,准备好,开始下一小节。陷井!试一下,你能找出下面这段程序的

28、错误吗?#include int*pPointer;void SomeFunction();int nNumber;nNumber=25;/让指针指向 nNumber:pPointer=&nNumber;void main()SomeFunction();/为 pPointer赋值/为什么这里失败了?为什么没有得到25coutValue of*pPointer:*pPointerendl;这段程序先调用了SomeFunction 函数,创建了个叫nNumber的变量,接着让指针pPointer 指向了它。可是问题出在哪儿呢?当函数结束后,nNumber被删掉了,因为这一个局部变量。局部变量在定

29、义它的函数执行完后都会被系统自动删掉。也就是说当SomeFunction 函数返回主函数 main()时,这个变量已经被删掉,但pPointer 还指着变量曾经用过的但现在已不属于这个程序的区域。如果你还不明白,你可以再读读这个程序,注意它的局部变量和全局变量,这些概念都非常重要。但这个问题怎么解决呢?答案是动态分配技术。注意这在C和 C+中是不同的。由于大多数程序员都是用C+,所以我用到的是C+中常用的称谓。动态分配动态分配是指针的关键技术。它是用来在不必定义变量的情况下分配内存和让指针去指向它们。尽管这么说可能会让你迷惑,其实它真的很简单。下面的代码就是一个为一个整型数据分配内存的例子:i

30、nt*pNumber;pNumber=new int;第一行声明一个指针pNumber。第二行为一个整型数据分配一个内存空间,并让pNumber指向这个新内存空间。下面是一个新例,这一次是用double 双精型:double*pDouble;pDouble=new double;这种格式是一个规则,这样写你是不会错的。但动态分配又和前面的例子有什么不同呢?就是在函数返回或执行完毕时,你分配的这块内存区域是不会被删除的所以我们现在可以用动态分配重写上面的程序:#include int*pPointer;void SomeFunction()/让指针指向一个新的整型pPointer=new int

31、;*pPointer=25;void main()SomeFunction();/为 pPointer 赋值coutValue of*pPointer:*pPointerendl;通读这个程序,编译并运行它,务必理解它是怎样工作的。当 SomeFunction调用时,它分配了一个内存,并让 pPointer指向它。这一次,当函数返回时,新的内存区域被保留下来,所以pPointer始终指着有用的信息,这是因为了动态分配。但是你再仔细读读上面这个程序,虽然它得到了正确结果,可仍有一个严重的错误。分配了内存,别忘了回收太复杂了,怎么会还有严重的错误!其实要改正并不难。问题是:你动态地分配了一个内存空

32、间,可它绝不会被自动删除。也就是说,这块内存空间会一直存在,直到你告诉电脑你已经使用完了。可结果是,你并没有告诉电脑你已不再需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致系统崩溃。所以这是很重要的,在你用完它以后,请释放它的空间,如:delete pPointer;这样就差不多了,你不得不小心。在这你终止了一个有效的指针(一个确实指向某个内存的指针)。下面的程序,它不会浪费任何的内存:#include int*pPointer;void SomeFunction()/让指针指向一个新的整型pPoint

33、er=new int;*pPointer=25;void main()SomeFunction();/为 pPointer赋值coutValue of*pPointer:*pPointerendl;delete pPointer;只有一行与前一个程序不同,但就是这最后一行十分地重要。如果你不删除它,你就会制造一起“内存漏洞”,而让内存逐渐地泄漏。(译者:假如在程序中调用了两次SomeFunction,你又该如何修改这个程序呢?请读者自己思考)传递指针到函数传递指针到函数是非常有用的,也很容易掌握。如果我们写一个程序,让一个数加上5,看一看这个程序完整吗?:#include void AddFi

34、ve(int Number)Number=Number+5;void main()int nMyNumber=18;coutMy original number is nMyNumberendl;AddFive(nMyNumber);coutMy new number is nMyNumberendl;/得到了结果23吗?问题出在哪儿?问题出在函数AddFive 里用到的 Number 是变量 nMyNumber 的一个副本而传递给函数,而不是变量本身。因此,Number=Number+5 这一行是把变量的副本加了5,而原始的变量在主函数main()里依然没变。试着运行这个程序,自己去体会一下

35、。要解决这个问题,我们就要传递一个指针到函数,所以我们要修改一下函数让它能接受指针:把void AddFive(int Number)改成 void AddFive(int*Number)。下面就是改过的程序,注意函数调用时要用号,以表示传递的是指针:#include void AddFive(int*Number)*Number=*Number+5;void main()int nMyNumber=18;cout 七我眼中的指针-学习指针不可少的好文章我眼中的指针-学习指针不可少的好文章为初学者服务。这是我的帖子的宗旨。我也是个初学者(强调了无数遍了),我以我的理解把初学者觉得难懂的东西用浅

36、显的语言写出来。由于小学时语文没学好,所以竭尽全力也未必能达到这个目的。尽力而为吧。指针是 c 和 c+中的难点和重点。我只精通 dos 下的 basic。c 语言的其它各种特性,在 basic 中都有类似的东西。只有指针,是 baisc 所不具备的。指针是c 的灵魂。我不想重复大多数书上说得很清楚的东西,我只是把我看过的书中说得不清楚或没有说,而我又觉得我理解得有点道理的东西写出来。我的目的是:1。通过写这些东西,把我脑袋中关于c 的模糊的知识清晰化。2。给初学者们一点提示。3。赚几个经验值。(因为贴这些东西没有灌水之嫌啊)第一章。指针的概念指针是一个特殊的变量,它里面存储的数值被解释成为内

37、存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。先声明几个指针放着做例子:例一:(1)int*ptr;(2)char*ptr;(3)int*ptr;(4)int(*ptr)3;(5)int*(*ptr)4;如果看不懂后几个例子的话,请参阅我前段时间贴出的文?lt;。1。指针的类型。从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:(1)int*ptr;/指针的类型是 int*(2)cha

38、r*ptr;/指针的类型是char*(3)int*ptr;/指针的类型是 int*(4)int(*ptr)3;/指针的类型是 int(*)3(5)int*(*ptr)4;/指针的类型是 int*(*)4怎么样?找出指针的类型的方法是不是很简单?2。指针所指向的类型。当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:(1)int*ptr;/指针所指向的类型是int(2)char*ptr;/指针所指向的的类型是char(3)int*pt

39、r;/指针所指向的的类型是 int*(4)int(*ptr)3;/指针所指向的的类型是 int()3(5)int*(*ptr)4;/指针所指向的的类型是 int*()4在指针的算术运算中,指针所指向的类型有很大的作用。指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的 类型 这个概念分成 指针的类型 和指针所指向的类型 两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。3。指针的值,或者叫指针所指向的内存区或地址。指针的值是指针本身存储的数值,这个

40、值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。以后,每遇到一个指针

41、,都应该问问:这个指针的类型是什么?指针指向的类型是什么?该指针指向了哪里?4。指针本身所占据的内存区。指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32 位平台里,指针本身占据了4个字节的长度。指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。第二章。指针的算术运算指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:例二:1。char a20;2。int*ptr=a;.3。ptr+;在上例中,指针ptr 的类型是 int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第 3 句中,指针

42、ptr被加了 1,编译器是这样处理的:它把指针ptr 的值加上了 sizeof(int),在 32 位程序中,是被加上了4。由于地址是用字节做单位的,故ptr 所指向的地址由原来的变量a的地址向高地址方向增加了4 个字节。由于 char 类型的长度是一个字节,所以,原来ptr 是指向数组 a的第 0 号单元开始的四个字节,此时指向了数组a 中从第 4 号单元开始的四个字节。我们可以用一个指针和一个循环来遍历一个数组,看例子:例三:例三:int array20;int*ptr=array;./此处略去为整型数组赋值的代码。.for(i=0;i20;i+)(*ptr)+;ptr+;这个例子将整型数

43、组中各个单元的值加1。由于每次循环都将八指针详解第一章。指针的概念指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。先声明几个指针放着做例子:例一:(1)int*ptr;(2)char*ptr;(3)int*ptr;(4)int(*ptr)3;(5)int*(*ptr)4;1。指针的类型。从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:(

44、1)int*ptr;/指针的类型是int*(2)char*ptr;/指针的类型是char*(3)int*ptr;/指针的类型是int*(4)int(*ptr)3;/指针的类型是int(*)3(5)int*(*ptr)4;/指针的类型是int*(*)4 怎么样?找出指针的类型的方法是不是很简单?2。指针所指向的类型。当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:(1)int*ptr;/指针所指向的类型是int (2)char*pt

45、r;/指针所指向的的类型是char (3)int*ptr;/指针所指向的的类型是int*(4)int(*ptr)3;/指针所指向的的类型是int()3 (5)int*(*ptr)4;/指针所指向的的类型是int*()4 在指针的算术运算中,指针所指向的类型有很大的作用。指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的 类型 这个概念分成 指针的类型 和指针所指向的类型 两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。3。指针的值,或者叫指针所指

46、向的内存区或地址。指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存

47、区是不存在的,或者说是无意义的。以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的类型是什么?该指针指向了哪里?4。指针本身所占据的内存区。指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32 位平台里,指针本身占据了4个字节的长度。指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。第二章。指针的算术运算指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:例二:1。char a20;2。int*ptr=a;.3。ptr+;在上例中,指针ptr 的类型是 int*,它指向的类型是int,它被

48、初始化为指向整形变量a。接下来的第 3 句中,指针 ptr被加了 1,编译器是这样处理的:它把指针 ptr的值加上了 sizeof(int),在 32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr 所指向的地址由原来的变量a的地址向高地址方向增加了4 个字节。由于 char 类型的长度是一个字节,所以,原来ptr 是指向数组 a的第 0 号单元开始的四个字节,此时指向了数组a 中从第 4 号单元开始的四个字节。我们可以用一个指针和一个循环来遍历一个数组,看例子:例三:int array20;int*ptr=array;./此处略去为整型数组赋值的代码。.for(i=0;ia;ptr

49、-b;ptr-c;又请问怎样通过指针pstr 来访问 ss 的三个成员变量?答案:*pstr;/访问了 ss 的成员 a。*(pstr+1);/访问了 ss 的成员 b。*(pstr+2)/访问了 ss 的成员 c。呵呵,虽然我在我的MSVC+6.0 上调式过上述代码,但是要知道,这样使用pstr 来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指针来访问数组的各个单元:例十二:int array3=35,56,37;int*pa=array;通过指针 pa 访问数组 array 的三个单元的方法是:*pa;/访问了第 0号单元*(pa+1);/访问了第 1号单元*(pa+2

50、);/访问了第 2号单元从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。所有的C编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个填充字节,这就导致各个成员之间可能会有若干个字节的空隙。所以,在例十二中,即使*pstr 访问到了结构对象ss 的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。因为成员 a 和成员 b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术标书

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

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com