指针数组和数组指针

一、指针数组和数组指针在定义上的不同
int* arr[3]; //定义了一个指针数组
int (*arr) [3]; //定义了一个数组指针
    1、本质区别

         指针数组和数组指针在本质上就有区别,指针数组是一个数组,数组里存放指针,数组指针是一个指针,指向一个数组。

    2、原理

         这两个定义区别就在于数组指针的定义给*arr带了一对括号,使其优先匹配,所以问题就在于运算符优先级,[]优先级高于*,所以在指针数组的定义中,arr优先和[]匹配,指明定义了一个数组,而且是int*类型的数组。而数组指针的定义中,我们先让*arr匹配,指明这是一个指针,并且是指向int [3]类型的指针。

    3、语法

         指针数组在定义时,因为是定义数组,所以[]中可以不给值,由初始化列表指定其元素个数。而数组指针在定义的时候[]中必须给值,因为这是定义指针,指针指向的数组有多少个元素必须确定,换句话说,如果[]中不给值,int []是一个不完整的类型,也就是指针指向了一个不完整的类型,这是不合理的。
         数组指针是一个指针变量,它接收的是一个和它指定类型相同的数组的地址。

二、再谈数组指针

         这里主要看一下下边两行代码的区别。

//arr是int[3]类型的数组
int * p = arr;
int (*q) [3] = &arr;
    1、先明确他们本质上的不同

         p是一个int *类型的指针,指向的应该是int型的变量,q是一个int (*) [3]类型的指针,指向的应该是int [3]类型的数组。

    2、共同点

         数组名在大多场合下指的是数组首元素的地址,所以将arr赋给p意思是p指向arr[0]这个int型的空间,将&arr赋给q意思是q指向arr(这里的arr指的是整个数组)。
       (1)地址空间

printf("%p\n", p);
printf("%p\n", q);

在这里插入图片描述
         通过这个可以看出,对pq指针按地址打印时,发现他们是一样的,从某种意义上来说,pq指向同一空间,或者说指向的空间首地址相同。
       (2)访问数组

printf("%d\n", p[1]);
printf("%d\n", (*q)[1]);

在这里插入图片描述
         pq都可以通过其特定的方式以相同的下标去访问到相同的数组空间。虽说代码看起来有些许不同,但是其对数组的访问所需下标是对应的。

    3、结合共同点看本质变不同

         虽说两者有一定的共同点,但是其本质还是不同的,而且看到(*q)[1]这样的代码之后会很好奇q[1]是一个怎样的状况呢,我们结合两个相同点来看一看。
         铺垫:在指针和数组中的下标访问符结合起来的时候,会起到和数组相同的效果。比如上述中的p[1]可以访问到arr[1]中的元素,其原理性相当于是指针和整数相加,p[1] == *(p + 1), 而p + 1的意思是在p的基础上往后偏移一个p所指向类型大小的空间。这就使得指针可以像数组那样用下标访问符来访问内存空间。
         有了这个知识点,我们来看这两行代码

printf("p:%p q+1:%p\n", p, p + 1);
printf("q:%p q+1:%p\n", q, q + 1);

在这里插入图片描述
         根据代码和结果分析一下,可以看到,pq地址相同,但是p+1q+1地址不同,算一下其差值就会发现,p+1p相差4个字节q+1q相差12个字节,而我们的数组是int [3]类型,一个元素是四个字节,整个数组是十二个字节,这就完全解释的通了,虽然pq看似其地址空间相同,但是他们一个是指向数组中的一个元素,而另外一个指向整个数组。
         还有上边提到了q[1],现在可以理解了,q[1] == *(q + 1),其打印的地址空间和q + 1相同,原因是q + 1为q往后偏移一个数组空间的首地址,q+1还是一个指向和原数组相同类型的指针,而*(q + 1)得到的是相当于和原数组相同的一个数组(虽然它不存在),那么打印这个数组空间就是打印其首元素地址,和q + 1一样。

三、总结

指针数组和数组指针有着本质上的不同,对数组指针进行深度剖析之后,会发现它在内存空间上和原理性上都于普通指针不同,以至于再去想一想都不知道该说他是一个一级指针还是二级指针,总之在想清楚这个之前必须对数组和指针分别理解清楚,理解透了之后,将两者放在一起从某种意义上说可以说数组就是指针。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值