二维数组在计算机中存储时,是按照行形式存储的。即把每一行看做一个整体,然后再把每一行的首地址进行索引,这样就变成了一个存储着每行首地址的一维数组。
例如对于二维数组num[2][2]={1,2,3,4};可以理解为是一个一维数组p,这个一维数组p有两个元素,分别为num[0]与num[1],num[0]存储着num数组第一行的首地址,num[1]存储着第二行的首地址。
int num[2][2]={1,2,3,4};
cout<<*num[0]<<endl;
cout<<*num[1]<<endl;
输出结果为1,3.分别是第一行与第二行的首元素。
二维数组用指针索引的方法有两种,一种是实用一维指针int *进行索引,一种是使用二维数组指针int (*)[2]进行索引,具体使用见代码。
1. 一维指针进行索引
int num[2][2]={1,2,3,4};
int *p1=num[0];
cout<<*(p1+3)<<endl;
cout<<p1[3]<<endl;
定义一个一维指针p1,把二维数组当做一维数组去进行索引,可以如第3行,通过指针索引,也可以如第4行,通过数组索引。
需要注意的一点,第二行num[0]可以看做是这个二维数组的起始地址。不可以使用int *p=num;这样的赋值方式,因为num是一个二维数组指针。可以通过指针类型强制转化,进行赋值:int *p=(int *)num
2. 二维数组指针进行索引
int num[2][2]={1,2,3,4};
int (*p2)[2];
p2=num;
cout<<*(*(p2+0)+1)<<endl;
cout<<p2[0][1]<<endl;
定义一个数组指针p2,p2的列数必须与指向的二维数组列数相同。这里必须给int (*p2)[2]加括号,因为[]的优先级是大于*的优先级。具体可以参考我的另一篇博客:http://blog.csdn.net/wb595972434/article/details/78933539数组指针可以像数组名一样,使用下标或者指针增加来进行索引。
总结:其实无论是方式1还是方式2,二维数组在内存中都是顺序存储的。因此不同的索引方式只是索引规则的不同而已,遵循一维指针及数组指针的使用方法即可正常索引。可以通过使用指针类型强制转换来实现方式1与方式2的转化。
二维数组做函数参数:
根据之前的介绍,二维数组函数参数可以有一下几种方式
1.func(int num[2][2]);
2.func(int num[][2]);
3.func(int (* p2)[2]):
4.func(int * p1)
需要注意的是,第1,2种方式是直接用二维数组做形参,二维数组做形参时,列数必须写出来,而行数不是必须的。第3种方式是使用数组指针的方式来作为函数形参。以上三种方式都可以在func中使用num[i][j]或者*(*(num+i)+j)的方式进行索引。第4种方式是使用一维指针的形式来代替二维数组,这种方式在使用时要注意,实际的func在调用的时候,需要对二维数组实参进行指针类型强制转换。使用这种方式时,func内只能使用p1[i]和*(p1+i)的方式索引值。