本博文由 西北工业大学MOOC 总结而来,以备以后回顾。 此次二维数组为自己增加的内容,如有错误欢迎留言指正
1、一维数组和指针 1.1、一维数组的地址数组由若干元素组成,每个元素都有相应的地址,通过取址运算符(&)可以得到每个元素的地址。 C++规定,数组名既代表数组本身,又代表整个数组的地址,还是数组首元素的地址。即a与a的第0个元素的地址&a[0]相同。例如, 数组名是一个指针常量,因为不能出现在左值和某些算术运算中,例如:
1.2、指向一维数组的指针变量定义指针时,用数组名初始化指针,即可将指针指向一维数组。指针的指向类型应和数组元素类型一致。例如:
1.3、通过指针访问一维数组元素由于数组元素的地址是规律性增加的,更具指针算术运算规则,可以利用指针及其运算来访问数组元素。 访问一维数组元素有以下四种方法:
2、二维数组和指针 2.1、二维数组的地址假如有一个二维数组:
int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};其中,a 是二维数组名。a 数组包含 3 行,即 3 个行元素:a[0],a[1],a[2]。每个行元素都可以看成含有 4 个元素的一维数组。而且 C 语言规定,a[0]、a[1]、a[2]分别是这三个一维数组的数组名。如下所示: a[0]、a[1]、a[2] 既然是一维数组名,一维数组的数组名表示的就是数组第一个元素的地址,所以 a[0] 表示的就是元素 a[0][0] 的地址,即
a[0] == &a[0][0];a[1] == &a[1][0];a[2] == &a[2][0];所以二维数组 a[M][N] 中,a[i] 表示的就是元素 a[i][0] 的地址,即
a[i] == &a[i][0];则 a[i]+j 就表示元素 a[i][j] 的地址,即:
a[i]+j == &a[i][j];同时由一维数组 a[i] 和 *(a+i) 等价,引申至二维有:
*(a+i)+j == &a[i][j]; 二维数组的首地址和数组名二维数组就是一维数组,二维数组 a[3][4] 就是有三个元素 a[0]、a[1]、a[2] 的一维数组,所以二维数组 a[3][4] 的第一个元素不是 a[0][0],而是 a[0] (第一行元素的地址),所以数组名 a 表示的不是元素 a[0][0] 的地址,而是 a[0] 的地址,即:
a == &a[0];//数组名代表数组第一行元素a[0]的地址而 a[0] 又是 a[0][0] 的地址,即:
a[0] == &a[0][0];则二维数组名 a 和 元素名 a[0][0] 的关系是:
a == &(&a[0][0]);//数组名代表数组第一行元素a[0]的地址二维数组的空间在内存中也是连续的地址。对于内存而言,没有维度而言,内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的。如下: 定义一个二维数组:
int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};或int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };按行输出为:
1 2 3 45 6 7 89 10 11 12其元素的地址输出为:
0X18FF18 0X18FF1C 0X18FF20 0X18FF240X18FF28 0X18FF2C 0X18FF30 0X18FF340X18FF38 0X18FF3C 0X18FF40 0X18FF44可以看出二维数组元素的地址在内存中是连续存在的。
2.2、指向二维数组的指针变量前面提到过,二维数组是由一行一行的一维数组组成的,如 a[0]、a[1],a[2];同时也是由一个一个的单独的元素组成的,如 a[0][0]、a[1][1]、a[2][2]。所以指向二维数组的变量可以有两种形式: 1)行指针:(常用) 行指针的定义如下,其指向的是二维数组的第0行。形式如下:
指针类型 (*指针名称)[数组列数] = 数组名/数组第0行元素地址;int a[M][N] = {.......};int (*p)[N] = a; //其中N是二维数组a[M][N]的列数, 是一个数字。或//**数组长度不能定义成变量int (*p)[N] = &a[0];//a == &a[0];//***************注意与指针数组作区别,int *p[4] 为指针数组,//其中包含四个int型指针,即p[0],p[1],p[2],p[3]都是int型指针,其中存储的都是地址值2)列指针: 列指针指向二维数组的第0个元素,其在形式上与指向单一对象的指针没有区别。形式如下:
指针类型 *指针名称 = 数组第[0][0]元素;int a[M][N] = {.......};int *p = &a[0][0];//指向二维数组第0行第0列的元素注意这两种指针都是一个指针,应与指针数组做区别(由多个指针元素组成的数组)。且指向二维数组的两种指针不能弄混,是因为二维数组的组成既是由行元素组成,也是由单个元素组成。行指针只能指向数组的行(一般指向第0行),其定义必须包含数组的列长度;列指针只能指向某一个元素,其相当于一个指向单独对象的指针。
2.3、通过指针访问二维数组的元素1)行指针:(常用) 定义一个二维数组和指向该数组的指针:
int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };int (*p)[4] = a;//将指针指向二维数组a的首地址则有如下的取值方式:
*(*(p+i)+j) == a[i][j];括号的运算优先级最高,所以最先运算 p+i,将指针指向第 i 行,再运算 * 号解引用得到第 i 行的首地址 &a[i],再运算 &a[i]+j,将指针指向第 i 行 第 j 列的元素的地址&a[i][j],再运算 * 号解引用得到元素的值 a[i][j]。 同理,还有其他取值方式:
*(*p) == *(a[0]) == *(&a[0][0]) == a[0][0];//value = 1*(*p+1) == *(a[0]+1) == *(&a[0][1]) == a[0][1];//value = 2*(*(p+1)) == *(a[0+1]) == *(&a[1][0]) == a[1][0];//value = 5*(*(p+1)+2) == *(a[1]+2) == *(&a[1][2]) == a[1][2];//value = 72)列指针: 列指针的实质是一个指向单独元素的指针,利用二维数组在存储空间上的连续性,也可对通过相应操作取得相应的值。举例如下:
# include int main(void){ int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int i, j; int *p = &a[0][0]; //把a[0][0]的地址赋给指针变量p for (i=0; i