1.二维数组的初始化
我们熟悉一维数组的初始化,即
int arr[]={1,2,3,4,5,6};
而二维数组的初始化和一维数组很像,区别就在一维数组只有一行,而二维数组可以有多行。
int arr[3][5]={1,2,3,4,5,6,7,8,9,10};
上述arr就是我们的二维数组,其类型是int[3][5]。其中3就是行数,5是列数。一般情况下,元素会默认从第一行开始填入,空余的位置会补0。
我们再来看一段二维数组的创建代码
int arr[3][5]={{1,2,3},
{2,3,4},
{3,4,5}}
这样创建的二维数组就是这样的
2.二维数组的内存
上述二维数组里,我们写入了三个一维数组。而二维数组中,元素的种类其实就是一维数组,如上述arr[3][5]就是由三个 arr[5] 一维数组组成。
我们知道一维数组的数组名一般情况下就是数组首元素的地址。
int arr[5]={1,2,3,4,5};//arr=&arr[0]
而二维数组的数组名也是其首元素的地址,只不过它的首元素是第一行的数组。
int arr[3][5]={{1,2,3},
{2,3,4},
{3,4,5}}//arr= *{1,2,3}这个数组的地址*
而这三个数组的地址是按下图规律分布的
我们知道了二维数组存储的是多个一维数组,而我们要获得某个具体的元素,就需要先访问其中的一维数组,进而访问一维数组中的某个元素。而我们对数组的访问,其实是通过其内存内存地址来实现的。
如我们要访问一维数组的某个元素
int arr[5]={1,2,3,4,5};
arr[3]//我们访问第四个元素
//编译器会将arr[3]这个代码转换成 *(arr+3) ,arr就是首元素的地址(arr+3)就4这个元素的地址
而我们要访问二维数组中的某个元素
int arr[3][5]={{1,2,3},
{2,3,4},
{3,4,5}};
arr[2][1];//编译器会先执行arr[2],即*(arr+2),获得第三行的一维数组,再从一维数组中访问目标元素。
通过上述讨论,我们进一步思考,会发现二维数组存储的,可以看作是多个一维数组的内存地址。因此我们可以通过指针模拟二维数组。
int arr1[]={1,2,3};
int arr2[]={2,3,4};
int arr3[]={3,4,5};
int * arr[3]={&arr1,&arr2,&arr3};
3.二维数组的传参
int arr[3][5]={{1,2,3},
{2,3,4},
{3,4,5}};
最容易理解的传参可以写成
void test(int arr[3][5]);
但我们知道二维数组的数组名是它首元素的地址,即第一行数组的地址,因此它传递的也可以是一个数组指针
void test(int (*P)[5]);