关于数组的那些事

 hello,everybody。

直接进入主题把。

现有一个二维数组 int a[5][5];

a,  &a      ,a[0],         &a[0]  这四个都分别代表什么呢?

答: 首先在 二维数组里  数组名 始终代表该数组的行指针。为什么要这样说呢?

 我给你从底层分析把,首先 a[1][1]是不是等价于*(*(a+1)+1) 对这个没有疑问把

然后呢... 这样是不是可以很明显的看到a是个行指针   对啊 已经和明显了 还不理解啊?好吧 那我再举个例子把。

a[2][3]等价于*(*(a+2)+3)  这样理解了吧 。  a 即就是a+0 代表着是第一行 ,那么 a+2 就移动到了第三行。

是的,我就是这样给你们证明出 对于二维数组来讲,数组名即就是行指针。那么a就是代表第一行的行指针了

(1)a代表什么

那么很好理解了  a+2代表第二行的行指针   看下列我给出的公式  那么 *(a+2)是不是就等于列指针了呢?对吧。

  行指针  列指针
*行指针=列指针 &列指针=行指针

(2)&a代表什么意义

说完了a ,接下来又是个&a  ,刚才说a是行指针,那么&a又是什么鬼鬼?

&a几乎没啥意义  这里大家只要弄懂&a+1  跟 &(a+1)的区别就行了

eg: int  a[2][2]

首先&a 是整个数组块的首地址  那么 &a+1  得到的内存地址就是 a[1][1]后面的地址了

然后 &(a+1)这样的写法就是错的 为什么说他是错的呢? a+1之后a跑到第二行了 这时他还是个行指针 之后 你再&行指针 就没有这种用法

必须先把(a+1)转化成列指针 即再前面加个* 号,然后才能取地址。说没有这种用法说的是不是有点牵强,是不是觉得接受不了,我也接受不了,可是编译器就是不认啊,就是认为他错了。好了 ,那再详细分析下把,为什么是错的呢?因为行指针已经是底层指针了啊 还要取地址 ,你要编译器上哪里给你取地址啊。 举个最简单的例子 int *p;这是一个指针变量吧,对,没问题 

那么我可以&p 拿到指针变量自己的地址 ,那我还能再加个&符号吗? 比如这样&&p; 仔细想想 这样是不是很明显的错误了。已经到最底层了,没法取地址了。 


看到我举得例子没 ,第一行数据是a的首地址转化为十进制的数据 ,第二行通过跟第一行比较 大了16个内存地址,刚好是4个int的大小。这样很直观的反应了 &a+1就是二维数组内存块最后的地址的下一个地址了。

用图片说明一下把~~~。


第三行是 a+1是第二行的地址 ,即为行指针  不能直接取地址,刚才解释的很清楚了,然后带个*,成了列指针,然后再&  即又是行指针。。哈哈~~变来变去  有意思 。其实还可以这么理解,因为 & 跟*抵消了。所以他还是个行指针。

(3)a[0] 又代表什么呢? 

    对没错了,首先它等价于*(a+0)那么很好理解了 ,他是个列指针 。

(4)&a[0]又代表什么呢?

由公式不难得到 &列指针=行指针  ,那么很简单了 &a[0]代表了一个行指针 ,他指向数组的第一行首地址。


最后介绍下单维度数组 eg; int a[5];


对于单维度数组,数组名等价于列指针 为什么?你可以把他看作一行,然后移动指针 比如 *(a+1)=>a[1],*(a+2)=>a[2] 是不是很明显觉得就是这样呢?为什么我要告诉大家这样子呢?因为 这样的话就很好理解对于单维度数组 &数组名 的意义了。 而且正好可以运用给的公式 &列指针=行指针;

如果你 int  a【5】,然后执行代码  &a+1(用公式很容易得出这是个行指针) 编译器会提示你这段代码有警告为啥呢。因为它由首地址移动到第二行的行首地址了 ,而对于单维度数组,第二行没有的地址根本没有定义呢,所以会警告的。

对于单维度数组来讲,你也可以把他看作一个特殊的二维数组,把他的每个元素想象成一块内存地址,可以放好多值,但是它每个元素 的那一块内存地址只存了一个值。

为什么我要这么理解呢?其实我这样说时有根有据的,当你动态申请二维数组的时候,你现在回想下过程是不是很类似呢?

以下是动态申请二维数组c【5】【5】的大致过程

  int ** c=(int**)malloc(sizeof(int*)*5);

for(int a=0;a<5;a++)

{

    c[a]=(int *)malloc(sizeof(int)*5);

}

好了,对于数组就先分析到这里,如果以后还有补充的...

总结: 


对于单维度数组:数组名等价于列


指针,


对于二维数组,数组名等价于行指


针。



猜你喜欢

转载自blog.csdn.net/huijiaaa1/article/details/78945398