自己学C++的时候就碰到过这个问题,是在NCR的课本里碰见的一个习题。上网查了,感觉没什么帮助。网络上差不多就是说:
*int p[Length]是申请了一个Length长度的数组,然后这个数组里面的每一个元素全部都是指针。
*int(p)[Length]则是申请了一个指向Length长度的指针
然后我就开始各种好奇:一个指针指向一个元素,怎么会一个指针指向一排的元素呢?难道是跟数组一样,有一个代表性的地址(如&array[0]),然后让指针指向数组的首地址就是指向整个数组一样吗?由此,我还很好奇类的地址,因为类是有一个独立的地址,那么这个地址难道也是指向一捆元素吗?
好吧,今天先不讲类,还是就题论题,我们来区分**int *p[Length]和int(*p)[Length]**吧!
int(*p)[Length]存在的意义
不知道有没有小伙伴是酱紫想的:
int* p2;
int a[2][3];
p2 = a;
酱紫是错误的哦……
这个二维数组可以理解为定义了两个数组,
分别为a[0]和a[1],一个指针没法指向两个数组啊
(那就整两个指针呗)
其实C++还提供了一种挺NB的写法,没错,就是今天介绍的这玩意儿
*int(p)[Length]
二维数组的本质是一维数组
在计算机的内存空间中,计算机没有人这么“聪明”,所以计算机会把二维数组自动处理成一维数组。
以下代码证明了这一点:
for (int i = 0; i <= 2; i++)
for (int j = 0; j <= 1; j++)
a[j][i] = i + j+i*j;
为了保证数组元素尽量不相同,故意这么计算
所以你眼中的二维数组是酱紫:
然而计算机眼中的是酱紫,
在内存空间中我们可以发现酱紫的数据:
由此可见尽管数组是二维数组,它们在内存空间中仍然连续
VS的内存怎么看
int类型占据四个字节,一个字节一个地址
但是,同学,这个地址是倒着看的!
这幅图片中,如果把这个储存单位的数据是100000,如果把它当成A08601来计算,那估计得到的是一个夸张且离谱的数据……
而倒过来,则是0186A0,这样就正常了
int(*p)[3]指针的赋值问题
int(*p)[3]指针仅仅接受二维数组的指针,并且要求第二维长度必须和这个3相同。以下是合法赋值:
int(*p2)[3];
int a[2][3];
p2 = a;
a数组的2无所谓的,随便什么都可以
但如果是
int(*p2)[3];
int a[2][4];
p2 = a;
那就显然是非法的了
这样子,p2指针便获得了a数组的控制权
此时你可以像使用数组一样输出p[0][0]
这是合法的
如果你问三维数组该怎么办,那就把指针和数组各加上一个维度即可
int(*p2)[3][4];
int a[2][3][4];
p2 = a;
反正就是都要对齐,数字啥的一个都不能糊弄
int(*p)[3]指针的头部
前面已经说过,int a[2][3];
相当于定义了两个长度分别为4的一维数组
而且数组名分别为a[0]
和a[1]
那么这个a[0]就是a[0]数组的地址(数组名即地址)
所以int(*p)[3]指针的头部就是a数组的头部
a数组的头部就是a[0]的头部
那么这里有一种很腻害的写法:(这种写法比较特殊,不要过于深究,暂时没发现这种语法和其它语法有什么共通之处。只能死记硬背了)
(*p)[2]
这个的意思就是取a[0][2],因为p指针默认指向a数组的头部!
那如果要取a[1][1]怎么办?
那就是*(p[1]+1)
往前推一个地址即可