一维数组和一级指针的相同和差异
一维数组的名字大部分情况下可以当成一个常指针来看,也就是说:
int a[3] int * const p;
则数组名a可以在大部分p能用的地方使用,有两种情况比较特殊:
- p可以在定义是初始化一个地址如:int *p const = new int[100];,而且这也是唯一的初始化他的机会。而数组则是有操作系统载入可执行文件时初始化内存空间的。
- sizeof运算符对p计算将获得指针的长度(现在一般为4),而对数组名则得到数组占有的所有字节数。
在内存排布上,一维数组和一阶指针指向的内存是完全一样的。
高维数组和高阶指针
对于高维数组(以二维为例,其他完全一样),情况和一维数组完全不一样。例如对于数组和指针:
int a[3][4] int**p;
他们就没有任何可比性。初学者从一维数组中的知识简单的推断出a是一个等价于int**的东西,*a就可以得到一个 int*的值,这其实是完全错误的。
从内存排布上,数组按照先低维后高维的顺序一次排列数组的每个元素。其中低维到高维是指定义数组时,离数组名越近的维为低维,反之为高维,例如上面这个数组,3就是低维的维数,4为高维的维数,因此,在内存中,上面这个数组占有12个int单元,所有单元靠在一起,其顺序则为
a[0][0],a[0][1],a[0][2],a[0][3] a[1][0],a[1][1],a[1][2],a[1][3] a[2][0],a[2][1],a[2][2],a[2][3]
如果a是一个和二阶指针等价的常量,那么他的值应该指向一个指针数组才对,而实际上这样的指针数组是不存在。
从前面这个排布还可以看出一个问题,在排列过程中,数组的最低维不确定是没有关系的,但是为了安排好数组元素的先后顺序,高维的维数必须确定,也就是说在使用数组类型来定义指针时,必须首先确定高维,例如:
int (*p)[3] = new int[4][3]
是可以的,但是
int (*p)[] = new int[4][3]
就不行。
回到一维数组
仔细考虑一维数组和多维数组,是不是编译器对一维数组特殊处理了?其实也不是,数组名其实代表的是数组对象也就是其第一个元素的地址,从这个角度讲,一维数组名a代表了a[0]的地址,二维数组名a代表了a[0][0]的地址,高维数组的名字从这个意义讲更接近1阶指针.