C++指针和二维数组
在C++中,二维数组元素值在内存中是按行的顺序存放的,即先存二维数组的第一行数据,然后再存储第二行数据,一次类推,可以把它看成是一个特殊的一维数组。因此,与一维数组类似,可用指针变量来访问二维数组。我们可以像使用一维数组一样,对二维数组进行操作。但是那样非常麻烦,所以C++提供了关于二维数组的单独操作方法。
首先搞清楚三个概念:
1.二维数组行首地址
二维数组各元素按行排列可写成矩阵形式,若将第i行中的元素a[i][0])、a[i][1]… a[i][n]组成一维数组a[i](i=0, …,n),则有:
a[0] = (a[0][0], ..., a[0][n])
a[m] = (a[m][0], a[m][1], …, a[m][n]
因为数组名可用来表示数组的首地址,所以一维数组名a[i]可表示一维数组(a[i][0], a[i][1], a[i][2], ...,a[i][n])的首地址&a[i][0],即可表示第i行元素的首地址。因此,二维数组a的第i行首地址(即第i行第0列元素地址)可用a[i]表示。
一维数组的第i个元素地址可表示为“数组名+i”,因此一维数组a[i]中第j个元素a[i][j]的地址可表示为a[i]+j,即二维数组a中第i行第j列元素a[i][j]的地址可用a[i]+j来表示,而元素a[i][j]的值为*(a[i]+j)。
2.二维数组行地址
为了区别数组指针与指向一维数组的指针,C++引入了行地址的概念,并规定二维数组a中第i行地址用a+i或&a[i]表示。行地址的值与行首地址的值是相同的,即a+i = &a[i] = a[i] = &a[i][0],但两者类型不同,所以行地址a+i与&a[i]只能用于指向一维数组的指针变量,而不能用于普通指针变量,如下所示:
int a[3][3];
int *p = a + 0
对于上面两行语句,编译第二条指令时将会出错,编译系统会提示用户p与a+0的类型不同。如果要将行地址赋数组指针变量,必须用强制类型转换,如下所示:
int *p = (int *)(a + 0);
二维数组名a可用于表示二维数组的首地址,但C++规定该首地址并不是二维数组中第0行第0列的地址,即a != a[0][0],而是第0行的行地址,即a = a+0 = &a[0]。
3.二维数组的元素地址与元素值
知道了二维数组的行地址与行首地址后,可以讨论二维数组的元素地址。
因为a[i] = *(&a[i]) = *(a+1),所以*(a+1)可以表示第i行的首地址。因此二位数组第i行的首地址有3种表示方法,即a[i]、*(a+1)、&a[i][0]。
由此可推知,第i行第j列元素a[i][j]的地址有4种表示方法,即a[i]+j、*(a+i)+j、&a[i][0]+j、&a[i][j]。
而第i行第j列元素a[i][j]的值也有4种表示方法:*(a[i]+j)、*(*(a+i)+j)、*(&a[i][0]+j)、a[i][j]。
二位数组有关行地址、行首地址、元素地址、元素值的各种表示方法归纳:
第i行 行地址a+i、&a[i]第i行 首地址(第i行第0列地址)a[i]、*(a+i)、&a[i][0]元素a[i][j]的地址a[i]+j、*(a+i)+j、&a[i][0]+j、&a[i][j]第i行第j列元素值*(a[i]+j)、*(*(a+i)+j)、*(&a[i][0]+j)、a[i][j]