作者:MiTu_-_
本帖内容著作权归作者所有,转载请务必保留本文链接
二维数组
二维数组其实是一维数组的扩展。(这句话要记住哟!)
- 比如我们这样定义一个一维数组:
int a[ 2 ];
那么数组a就有两个个元素;如果此时再在每个元素里面定义5个数组,这样一个一维数组就扩展成了一个二行五列的二维数组了。 - 比如我们这样定义一个二维数组:
int a[ 2][ 5 ];
这就是一个2* 5的二维数组了。
可以这样理解:
- 一维数组 int a[ 2 ];
a 表示数组的首地址,即a[ 0 ]的地址, - 那么扩展到二维数组 int a[ 2 ][ 5 ];
其实就是往一维数组a[ 0 ]里面再装进去5个元素,那二维数组的a就表示整个一维数组的 a[ 0 ] 的首地址地址,也就是含有5个元素的数组的首地址,如果你理解数组指针的话(如果不理解的小伙伴可以先看看我的上一篇【数组指针】),那么a[ 0 ] 其实就是一个数组指针,即 int (*p)[0];
一定要把二维数组的一行看成是一个整体!!!
(因为它的实质是:在一维数组里的元素里再次进行扩展)
我就用一个代码来演示:
#include <stdio.h>
int main()
{
/* 1) */ int a[2][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10} };
int (*p)[5] = a;
/* 2) */ printf("*(a+1): %p\n", *(a + 1));
/* 3) */ printf("a[1]: %p\n", a[1]);
/* 4) */ printf("&a[1][0]: %p\n\n", &a[1][0]);
/* 5) */ printf("*a[1]: %d\n", *a[1]);
/* 6) */ printf("a[1][0]: %d\n", a[1][0]);
/* 7) */ printf("**(a+1): %d\n\n", **(a + 1));
/* 8) */ printf("*p + 1: %p\n", (*p + 1));
/* 9) */ printf("*(*p + 1): %d\n", *(*p + 1));
/* 10) */ printf("*p[1]: %d\n\n", (*p)[1]);
/* 11) */ printf("*(p + 1) + 1: %p\n", *(p + 1) + 1);
/* 12) */ printf("**(p + 1) + 1: %d\n", *(*(p + 1) + 1));
/* 13) */ printf("*p[1]: %d\n", *(p[1] + 1));
return 0;
}
剖析代码
1)第一行先定义了一个2 * 5的二维数组,第一行的值为1,2,3,4,5;第二行的值为6,7,8, 9,10。
2)接着打印*(a+1),结果是地址,我们该怎么理解里面的a + 1 和 * 呢?
根据前面所说的:
- a 是二维数组第一行数组的首地址(其实就是一维数组的首地址,即一维数组的 a[ 0 ] )。
- a + 1 是二维数组第二行数组的首地址(其实就是一维数组的第二个元素的地址,即一维数组的 a[ 1 ] )。
- *(a + 1) 是二维数组的第二行数组的第一个元素的地址(和数组指针相同)。
可以把上面的步骤理解为:
① 找到一维数组。取数组的首地址。
② 到一维数组里的第二个元素去。取数组的第二个元素的地址。
③ 到一维数组里的第二个元素里的第一个元素去。取数组的第二个元素里第一个元素的地址。
3)打印a[ 1 ] ,结果是地址。
a[ 1 ] 就表示第二行数组的首地址(相当于一维数组里第二个元素的地址)。
4)打印 &a[ 1 ][ 0 ],结果是地址。
a[ 1 ][ 0 ] 就表示第二行数组第一个元素的内容了,再用取址运算符&就得到地址了(相当于取出一维数组里第二个元素里第一个元素的地址)。
5)打印*a[ 1 ],结果是6.
由上知 a[ 1 ]是第二行数组第一个元素的地址,再用取值运算符 * 就得到里面的内容了。
6)打印a[ 1 ][ 0 ]同上。
7)打印**(a + 1),结果是6.
由上知 *(a + 1)表示二维数组第二行首元素的地址,再用 取值运算符 * 就得到里面的内容了。
8)到了这你应该会对二维数组有深刻的理解了吧。其实二维数组和数组指针是有关系的。比如:
int a[ 2 ][ 5 ];
int (*p)[ 5 ] = a;
那么 p 就相当于 a[ 0 ] 了。都是指向二维数组第一行数组的首地址。
*p 则为第一行数值首元素的地址。
printf("*p + 1 : %p\n", *p + 1);
- p为二维数组a,即 a[ 0 ],也就是第一行数组的首地址。
- *p 是指二维数组a[ 0 ][ 0 ],也就是第一行数组首元素的地址。
- 再加1,就是二维数组a[ 0 ][ 1 ],也就是第一行数组的第二个元素的地址。
9) *( * p + 1) ,
10) (*p)[ 1 ]; 结果为2.
由8)知可知,要打印的就是第一行数组第二个元素的地址。
如果看了我的上一篇【数组指针】的同心可能就会发现,这里和那里的代码是几乎相同的。
for(i = 0; i < 5; i++)
{
printf("%d\n", *(*p + i));
printf("%d\n", (*p)[i]) ;
}
11)打印 *(p + 1) + 1,结果为地址。
- p是第一行数组的首地址。
- p + 1 是第二行数组的首地址。
- *(p + 1) 是第二行数组首元素的地址。
- 再加1,就是第二行数组第二个元素的地址。
12)打印*(*(p + 1) + 1) ,结果是7。
由11)知,再加上取值运算符就是取第二行第二个元素的内容了。
13)打印*(p[1] + 1) ,结果是7。
这里其实用到的是指针数组的知识(不懂的小伙伴可以先看看我的上一篇【指针数组】)
- 在上面我定义的二维数组中,可以把它看成一个一维数组,里面有两个指针,分别指向了含有5个元素的数组首元素的地址。
- 那么p[ 1 ] 则表示指针指向了第二个数组首元素的地址。
- 再加1,表示指向了第二个数组第二个元素的地址。
- 外面再加上取值运算符 * 就得到第二行第二个元素地址里的内容了。
二维数组的内容就到这里了。
不知道大家是这样呢
还是
赠人玫瑰,手有余香!!!还望大家随手点个赞哟(^U^)ノ~YO