指针的指针、数组指针以及指针数组
May 29th, 2007 by king
最近好像是跟指针卯上了,发现以前真的学得不好,太多的东西是模模糊糊的。可能是因为S现在做的项目有太多地方使用到指针,而且有的时候用到复杂的指针,所以才觉得有必要好好的研究下,这样可以减轻S的负担,也为我以后做准备吧。
要搞清一个指针首先必须搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区(这里只对int型进行说明,其他的类推)。
指针的类型:从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型,这是指针本身所具有的类型。例如:
(1)int *ptr; //指针的类型是 int * 整型指针
(2)int **ptr; //指针的类型是 int ** 指针的指针
(3)int (*ptr)[3]; //指针的类型是 int(*)[3] 数组指针
(4)int *ptr[3]; //指针的类型是 int*[3] 指针数组
指针所指向的类型:
(1)int *ptr; //指针所指向的类型是 int 指向整型
(3)int **ptr; //指针所指向的的类型是 int * 指向整型指针
(4)int (*ptr)[3]; //指针所指向的的类型是 int()[3] 指向整型数组
(5)int *ptr[3];//指针所指向的类型是 int[] 指向指针数组的第一个单元
指针的值(又称指针所指向的内存区或地址):
指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。
指针本身所占据的内存区:指针类型本身占据的内存空间,在32位平台中,指针本身占据4个字节的长度,可以使用sizeof(指针类型)来测试下指针占据的存储空间。
以上是预备知识,接下来言归正传。
指针的指针:这个比较简单,如下代码1:指针pni指向整型变量ni,pni的值为ni所在内存中的地址,指针的指针ppni指向一个整型指针,ppni的值为指针pni所在的存储单元的地址。
- int ni=10;
- int* pni=∋
- int** ppni=&pni;
数组指针:顾名思义,指向数组的指针,这里一定要区分指向数组首单元的指针和数组指针的区别。如下代码2:
int narr[3];
int *p=narr;
在以上代码中,narr只是一个指代数组首地址的指针,而不是一个指向数组的指针。所以p只是一个指向数组首地址的指针,。这个例子在《指针和数组名的区别》文章有详细介绍。
数组指针的使用见下代码3:
- int array[2][3] = {{1,2,3},{4,5,6}};//二维数组看作是两个一维数组
- int (*pa)[3]; //申明一个数组指针
- //array[0]指代二维数组中{1,2,3}的首地址,那么&array[0]是数组指针型
- pa = &array[0];
- cout<<(*pa)[0]<<"|"<<(*pa)[1]<<endl;
- cout<<**pa<<endl;
- cout<<*(*pa+2)<<endl;
- pa++;
- cout<<(*pa)[0]<<"|"<<(*pa)[1]<<endl;
- cout<<**pa<<endl;
- cout<<*(*pa+2)<<endl;
以上代码中第三行定义的pa是指向一个3维数组的数组指针。*pa就是一维数组的指针,自然可以使用(*pa)[i]的方式访问数组,而*pa+1则是(*pa)[1]这个元素的地址,所以自然得到第5,6,7行所注释的输出。经过pa++语句,由于pa是数组指针,后来pa中存放的地址应该是*pa+sizeof(array[0]),所以现在*pa就是一维数组{4,5,6}对应的首地址,同理得到第9,10,11行所注释的输出结果。
指针数组:也就是指针的数组,存放指针的数组,数组中的元素是指针。
例如:
- int n1=10;
- int n2=20;
- int* np[2]={&n1,&n2};
- cout<<*(np[0])<<endl;
- cout<<*(np[1]);//输出20
上述代码的第三行定义了一个指针数组,数组中含有两个元素,分别是n1、n2的地址,np[0],np[1]就是对应的这两个地址,所以*np[0],*np[1]分别是10,20
对于指针的指针、数组指针、指针数组,我们还可以给出更为直观的定义方法:
指针的指针:
typedef int* intP;
intP* p;
数组指针:
typedef int intArray[2];
intArray* p;
指针数组:
typedef int* intPtr;
intPtr p[2];
由于一些运算符优先级不同(*的优先级比[]低),所以在适当的时候使用typedef可以有效的避免迷惑性。
这几天的研究结束了我和S对指针的困惑,所以作此总结,希望对大家都有帮助。
That’s very clear.
Thank u for all these complete analysis ~~ That’s really a headache to many of us.
You did a necessary and helpful job~