1.指针的本质
在信息工程中指针是一个用来指示一个内存地址的计算机语言的变量或中央处理器(CPU)中寄存器.指针一般出现在比较近机器语言的语言,如汇编语言或C语言。纯面向对象的语言如Java一般避免用指针。指针一般指向一个变量或者函数。在使用一个指针时,一个程序既可以直接使用这个指针所储存的内存地址,又可以使用这个地址里储存的变量或函数的值。
c语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是c语言的灵魂,一点都不为过。C++作为从C语言发展而来的一门高级语言,他并没有摒弃指针,而是积极的采纳他.同时又注入了面向对象的高级思想,这使得C++成为了全世界迄今为止最为优秀的语言.
C++中的指针一直被初学者视为很神秘的东西.其实指针的概念很简单.我们可以把他看作一种数据类型,定义一个指针变量就像定义一个int,char型一样的变量.只不过我们往int里面存整数,往char型里面存字符,而往指针里面呢,存放的是地址,内存地址.我们只要记住一点,在高级语言里
2.指针的用法
既然我们说指针是一个变量类型,那么在继续深入了解指针之前我们先来了解一下什么叫做变量类型.
我们知道,所有的数据最终都是放到内存中才能被使用,也即是说,所有的数据,不管你是如何定义的,最终都将反映为一段内存空间.那么我们声明为某种变量类型之后有什么用呢?其实有两个用途.一个是限定内存占用大小.一般来说编程语言总要为数据设定不同的内存占用空间以满足不同应用的需求.尤其是在内存吃紧的嵌入式等应用,经常可是要用到bit型的,如果都用4个字节那是省事了,但是带来的空间消耗可是很大的.类型定义的第二个用途是约束操作.例如我int型的数据可以相乘,但是char型不可以不同的数据类型应该具有不同的操作.所以我们用类型定义来实现这种约束.
所以我们可以看出,指针无非存放的东西有点不同,其余的与其他数据类型没有什么不一样.指针变量本身占用了4个字节的空间来存放内存地址,即可以寻址到2的32次方即4G的内存地址空间.他有两个基本操作符,一个是*号(取地址中存放的值),一个是&(取变量地址).
我们先来看下面这段简单的代码
int aint = 3;
int* pint;
pint = &aint;
当定义了一个int型变量之后,C++会该变量分配一块内存空间,然后把3转换成4个字节初始化这片内存空间.在这里,我们要知道,其实变量名就相当于某个寄存器的别名,也就是地址空间的名字.我们使用这个变量名.就像使用地址空间上面存放的值一样.如果我们要得到aint这个变量的地址,我们可以用&aint来获得.程序下面又定义了一个指针变量pint,他是用来存放aint变量的内存地址的.那么我们如何使用指针呢?一般来说我们不用到变量的地址,我们更关心的变量的值,即地址中所存的值.我们用*号操作符来获取aint的值.然后输出.
指针和指向的变量之间的关系如下图所示.
那么既然指针是一类数据类型,为什么我们不用一种统一的数据类型的名字,例如pointer来定义一个指针变量呢?这是由于指针存放东西的特殊性造成的,指针存放的是内存地址,需要的时候我们可以取出内存地址中的数据来.问题是,我们如何去取这块内存中的数据呢??取两个字节?取四个字节?还有,取出来的数据他有什么操作呢??他可以相乘吗?我们要知道机器是很笨的,他什么都不知道,他只知道我们给他设定的规则. [Page]
还记得我们上面说过的数据类型的两大用途吗?用”基本数据类型 *”这样一种方式来定义一个指针变量的意义正在于此.机器将按照我们设置的类型(int*)取出aint地址上的四个字节的数据,然后将数据格式化成int型数据,这样数据的操作就受到约束了.C++中还甚至允许我们定义指针类型为void*型,表明我们暂时只需要指针的首地址,不需要立即对其数据进行格式化.
*函数指针*
指针作为存放地址的变量,那么他自然可以存放任何东西的地址,例如函数.这就是函数指针了.函数指针的声明格式如下:
函数返回值类型(*指针变量名)(参数类型列表) = &函数
或者是
typedef 函数返回值类型 (*函数类型名)(参数类型列表)
函数类型名 函数指针 = &函数;
我们来看一个典型的应用
int getmax(int a,int b)...{ return a > b ? a : b;}typedef int (*Func)(int,int);int main()...{ Func pFuncFormat1 = &getmax; int (*pFuncFormat2)(int,int) = &getmax; cout<<(*pFuncFormat1)(3,5); cout<<(*pFuncFormat2)(3,5); return 0;}
上面这段代码首先定义了一个普通的比较大小的函数,然后在主函数中以两种风格定义了两个同样的函数指针,指向该函数.这样我们就在这个函数指针中存放了GetMax函数的入口地址了,注意这里跟普通的变量有些不一样.对GetMax函数用不用&号都是可以的,在使用时用不用*号也是可以的,效果是一样的.但是习惯上我们会采用上面这种风格来写程序代码比较好懂一点.还有要注意的是,函数指针一定要与函数声明的签名(也就是参数表)一致,还有返回值也要一致.
3.容易混淆的概念
**指针数组和数组指针的区别
这个也是C++里面比较容易混淆的一个定义.
你能看出下面的定义有什么区别吗?
1.int *PointerArray[3];
2.int (*ArrayPointer)[3];
1中定义的是一个指针数组.首先让我们先来了解一下什么叫做数组.数组就是同一类型元素的聚合.例如int array[3];定义了3个int型元素,并将其聚合在array这个数据结构中.数组本质上也是指针.即array变量本身存放的是上面这个数据结构的首地址.当我们用[]索引符号去访问数组对象时,其实就相当于调用指针操作符*取地址上的数据(注意,指针也可以应用[]索引符,或者数组\"名\"也可以应用*操作符,这也再一次说明了数组和指针具有一定的关系).那数组和指针有什么不同呢?我们说数组是一种常指针(关于常指针和指针常量我们待会再解释).了解到这一点之后我们再来看下指针数组是什么东西就很好理解了.指针数组说白了就是存放指针变量的数组.我们可以把int* 看作一种新类型,和int,char等基本类型等价的一种类型,然后再去看上面这个例子就很清楚了.