指针和数组名

想要清楚的知道指针和数组的本质区别还有处理方式,感觉绕不开看编译器是如何处理的了,有时间可以上知乎搜搜有什么编译类的书籍,或者找个懂编译的大神,在网上看到有一篇从编译器角度剖析数组名的,有所帮助,虽然没有说到足够深入让我理解指针和数组真正的本质是什么:
http://blog.chinaunix.net/uid-27004869-id-3301282.html

本文只是稍微说明一下自己的猜测和理解,可能存在有错的地方,主要还是觉得理解的不够深刻,有时间希望看看编译类的书籍。这个问题真的困扰我很久了,希望大神可以解释。

对于指针和数组名

指针和数组名虽然用法上很多时候是一样的,但其实是两个东西,数组更像是一种数据结构,但是可以转化成指针类型
很多时候数组名可以转化成指针类型让人不好理解,如下

char* argv[];
char* *p=argv;

为什么argv是char**类型的呢?
char* argv[]去分析, 第一步一定要去分析类型!分析类型很简单,不是数组就是指针!argv与[]结合是一个数组,然后存储的数据类型是char*,所以可以确定argv是一个指向char*类型的指针。
上面特地写成了char* *p这种形式,就是想说明,p是一个指针,指向了char*类型的数据(这就和数组名一样了)。

所以如何理解变量名的类型呢? 无论是多维数组还是指针,只有进行第一个结合*或者[]说明变量是数组还是指针。
比如,对于三维四维指针,都可以这样阅读,比如说char****p,p是一个指针,指向了char***,而不用读成指针的指针的指针的指针…
而对于多维数组,比如说int a[2][2],可以这么理解,首先a[2]说明是一个数组,数组中存储的类型是int [2](编译器把它处理成了存储数组的首地址),所以是一个指向数组的指针,即int(*)[]。

数组名强制转化成不匹配的指针类型

就像是double类型强转成int类型一样,一个本来应该是int(*)[]类型的指针,转化成了int**,如下

int a[2][3]={{1,2,3},{4,5,6}};
int **p=(int**)a;

这个时候p的值和a的值是一模一样的

cout <<p<<endl;
cout <<a<<endl;//两者完全相等

前面提及过了数组更像是一种数据结构,记录了该数组的维度,各个维度的上下界,还重载了*(解引用) +(加)等运算符,一旦完全转化成指针之后,就是一个指针,+以及*都没有重载成数组的形式,而是直接+4,没有维度信息了

cout<<*(p+1)<<endl;//结果是00000002,cout还把它当成一个地址来处理,实际上就是&a[0][0]这个地址偏移+1之后中的内容。
cout<<*(a+1)<<endl;//结果是&a[1][0],a是一个数组名,对+以及*都做了重载。


错误的用法,比如说想输出a[1][2]

cout<<*(*(p+1)+2)<<endl; //由于指针对+和*进行数组形式重载,所以该句等价于(*(a[0][1])+2),故而出错
cout<<*(*(a+1)+2)<<endl; //数组名对+和*进行了数组形式重载,所以该句等价于a[1][2]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值