数组指针VS指针数组

要搞清一个指针首先必须搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区(这里只对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 指向整型

(2)int **ptr; //指针所指向的的类型是 int * 指向整型指针

(3)int (*ptr)[3]; //指针所指向的的类型是 int()[3] 指向整型数组

(4)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:

void main()
{

    int array[2][3] = {{1,2,3},{4,5,6}};//二维数组看作是两个一维数组
    int (*pa)[3]; //申明一个数组指针,若(*pa)[3]中不为3则出错
    //array[0]指代二维数组中{1,2,3}的首地址,那么&array[0]是数组指针型
    pa = &array[0];//即(*pa)相当于array[0]。
    cout<<pa[0]<<"|"<<pa[1]<<"|"<<pa[2]<<endl;
    cout<<pa<<endl;
    cout<<*pa<<endl;
    cout<<(*pa)[0]<<"|"<<(*pa)[1]<<"|"<<(*pa)[2]<<endl;
    cout<<**pa<<endl;
    cout<<*(*pa+2)<<endl;
    pa++;
    cout<<pa[0]<<"|"<<pa[1]<<"|"<<pa[2]<<endl;
    cout<<pa<<endl;
    cout<<*pa<<endl;
    cout<<(*pa)[0]<<"|"<<(*pa)[1]<<"|"<<(*pa)[2]<<endl;
    cout<<**pa<<endl;
    cout<<*(*pa+2)<<endl;

}
输出为:

0012FF68|0012FF74|0012FF80

0012FF68

0012FF68

1|2|3

1

3

0012FF74|0012FF80|0012FF8C

0012FF74

0012FF74

4|5|6

4

6

 

以上代码中第三行定义的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可以有效的避免迷惑性。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值