现在的位置: 首页 > 综合 > 正文

可恶的C++指针

2012年12月09日 ⁄ 综合 ⁄ 共 3445字 ⁄ 字号 评论关闭

第三章 可恶的指针

一、开章有益

建章时间:一九九九年九月二十六日星期日晚上20:48:25

包括以下内容:

如果对一个指针所指向的最终地址不是很清楚的话,那么就使用作图法来理解吧!

指针、多级指针、指针数组、数组指针

数组、多维数组的各种交叉使用的心得

    关键:确定一个指针,什么情况代表地址,什么情况代表所包含的地址中的变量的值

printf使用%p可以按指针形式输出

指针的

 

指针概述和程序设计原理的讨论

                   二○○○年四月二十三日星期日晚上09:40:21

半年前我建立了这一章,可以说记录的很糙,可能是对指针使用的方法的常见情况用的不多,很难将书本上的内容真正转化成一个对指针理性的认识,从现在的角度看来指针真的是个很难也很重要的内容,要花很多的时间写程序和读程序才能慢慢的理解一个指针的含义,我认为如果要很清晰的理解指针的含义,要从汇编语言的角度就会比较容易。

一说到指针,使人难免想起数组,对于一开始学习C语言来说,数组可以是指针应用最多也最广的实体。

数组和指针加起来、混和起来,就连现在的我有时也要想上半天才能想明白,当然大面的东西是不会有什么难度,但有时人思路上的缺陷就难免产生很多的逻辑错误,所以我认为当你写程序用到指针时,比较好的办法就是将你绝对确定的值用指针表示后看它的输出结果是否是你的结果,这种办法如果使用几个极限数值的话,很大程度上正确性会有很高的把握。

初学指针时,对于指针十分善变的特性可能会将你搞的头晕脑胀,但这其实是正常的,这时学习对它们最好的方法就是把你见到所有关于指针的程序你先心算出结果后,再将程序编译后的结果对比,虽然你的结果错误率也许能达到80%,但你可以一点点的析程,从每一个错误中吸取经验。将它们记录下来,有朝一日你会发现你的经验变的重叠了的比例很大的时候,你那时可以说对指针就有60%的认识了,一般的问题是不会难到你的,但你要记住无论何时都把你心算的错误中得到一条条的理论,这对于指针是至关重要的。

 

对于一般的书本上说的很多的概念性的问题,我也不想重述。

对于一些比较成式化的东西说一说,在C中数组名代表数组的首地址,函数名代替着函数的入口地址。但在C++中对象名却并不代表着对象的地址。这些首地址的原因是在CC++转化成汇编形式的时候,这些函数,数组等都是一个标号,使用jmp指令或other call指令调用的。

指针的类型有很多种,可以说所有的数据类型都可以定义成相应的指针,甚至是指针的指针。

指针为什么会应用如此的广泛和繁杂,这与程序的原理是分不开的,在我们学程序设计,应多读一些关于程序原理、系统原理的程序的实现方法的书,会很有裨益。有时可能你觉得你看的东西很难一时用的上,或者你认为是东一笔西一笔,这没有关系,不用把你看的东西死记硬背,只把你感兴趣的内容做一个一般了解即可,但以后你达到了一个新的深度的时候,那些让你冥思苦想的问题,有时会从你读的那些天书里想到一道光明的灵感。

在你面前的PC在其硬件上说不是会一时间就有多大的变化,因此PC程序的原理也就不会变。就象学习指针一样,当将四面八方的原理和经验汇集起来的时候,你就会发现曾经的苦难都已过去,眼前是一片的阳光明媚。你应该高兴一天,在第二天的时候再投入到一个新的层次的学习。

在程序中无论是小到一个变量大到一个函数,类,结构等等,它们都会在内存中有一个真实的物理地址,当然在这个物理地址我们可以暂不理,只管把握我们程序中的逻辑偏移就可以了(这个基址的加入是硬件和操作系统的事)

对于函数,它的应用原理就是在使用它是使用call instruction 调用函数在内存的地址。数组可以使用程序设计上的数组名加下标的引用方式,但它本身要用它的地址,同样也可以使用指针。

说到这,其实指针就是一个让你可以在物理上操作你的硬件的一条捷径,因此它才会显得如些的重要。

指针的发展方向

C语言中指针的实现在编译上讲是很灵活的,这样规律的后果是指针的优点和缺点都是很极限化的,在C++上指针的使用被加入了很多的限制,比如在函数上使用原型,函数指针必须使用原型,这就要是为了重载函数。

虽然在很多的书上看到说CC++的编译器本身并不检查指针或数组的越界问题,其实不是不检查而是不能检查,because 指针就是指向实际地址,而编译是无论如何都不可以知道programmeridea(想法),so that(所以) ourselves must 保证指针指向的correctness(正确性)。

比如在C语言中我们对一个函数的声明很简单,即 [类型]<函数名>( ),无论这个函数有多少个或什么类型的参数,而在C++中函数的声明必须使用原型,虽然限制了指针的使用,但明确后的函数声明,使的C++中函数可以重载,安全性要大大的增强,可以说是对指针发展达到了一个新的境界。在C中指针的对数组的越界引用,编译程序是没有办法检查的。这时在C++中我们可以通过重载运算符的方法对引用进行必要的检查,当然这在很小的程序中是没有必要的。

函数指针,在C++中如果我们在定义函数指针的时候,必须要考虑到这样一个问题,即如果我们的函数的参数列表并不确定,即参数个数不定时,在C++中我们在声明这样的函数或者是函数指针的时候,我们必须使用以下方法:

For Example:1ch.cpp)

 

二、指针的初始化

    对于指针,如果它在定义时没有初始化,那么使用时动态的对它进行赋值是非常危险的,必须动态的为它分配内存(use malloc or new ect.)but if we在程序中静态的对它赋值,即在源程序中就对它指向的字符串的首地址赋给它是可以的,其实质就是这个给指针赋值的字符串本身在编译时会占用本身的长度的内存,这也是对指针变向的分配内存的方式。

    对于一个数组,如果我们在定义时没有初始化,则我们不能在定义以后再对它进行整体的赋值,但字符数组可以使用函数strcpy将值传递给它(actually still是单个evaluate)。

首先从一个多维数组的存储形式上看,无论是几维的多维数组,最后在内存中都是按照一维数组的形式顺序排列的,数组名代表这一个数组的首地址,这就使我们可以通过指针的算术运算,很容易的引用数组元素,但这样也必然带来了一些引用容易使我们思想上产生逻辑错的混乱,特别是使用指针数组和二级指针引用多维数组时这个矛盾显得特别的突出。所以有必要搞清楚一些基本情况。你要记住的一点是对于指针运算是在它现在所指向的层次进行的。

!!!对于相同类型的指针间进行互相赋值,notice a problem please,i.e.,这个两个指针指向的同一个地址,而不是为地址中的内容制作副本。

If we need to make a duplicate,we can first creat a that type object,then we use the content on the takeing a that type pointer of '*'

But, there still have a very significate problem ,  if we copy object is a 'struct' or 'class' or 'union' and they contains some other pointerthen we use above method can but make a non-holonomic(不完整)duplicate,because they still share part content

 

Example:

FILE *fp;

FILE duplicate=*fp;

 

The file pointer contains two charecter point,we must make two duplicate for them

Except 函数以外,我们使用两个指针有时是unreachable 我们要求的major aim并且还会因此形成一些很难发现的logic error

 

1、指针的类型和应用

指针可以指向任意一个类型的实体,关键的问题是要将指针定义成和被引用的实体,具有相同的类型,这样编译程序才能正确的处理指针。

 

1、取一个变量的地址                int var=10;int *P=&var;     

2、取一个数组的首地址           int var[10];int *p=var       

3、取一个数组元素的地址             int var[10];int *p=&var[i]    

4

抱歉!评论已关闭.