将二维数组作为函数参数
今天本来正在写一个稀疏数组的代码,要写的内容很简单,创建一个11x11的数组,将其中两个位置分别赋值为1、2,其余位置为0。然后输出数组看一下是否赋值正确。
正常是很简单的事情,但是我想把赋值和输出都作为函数来调用,于是引出了这么一个问题:
-
将一维数组作为参数传递,正常写法
//函数: void function(int a[]){ } //调用: function(a);
-
但是这种方式对于二维数组存在问题,编译器要求我们必须指定参数中二维数组第二维的大小,但是我为了代码泛性不想限制二维数组的大小,所以就进行了以下研究
理解数组与地址的关系
- 数组名是地址,这也是数组为引用传递的原因
- 一维数组的元素是单个的元素,而数组名就是第一个元素的地址,数组是顺序表(元素间地址连续)
- 二维数组的元素是一维数组,数组名就是第一个元素(一维数组)的地址,而一维数组的地址就是这个一维数组中第一个元素的地址。所以二维数组的数组名从数据上可以认为是第一个一维数组中第一个元素的地址,但是实际意义不同。
- 对于地址,我们可以通过*来得到该地址中的数据。对于二维数组,使用一个*得到的数据类型其实是一个数组,想要得到一个整形我们需要用两个*。
- 二维数组的“二维”其实只是逻辑上的概念,实际内存中与一维数组一样,都是所有元素连着排列(地址连续)。所以如果传入的参数为
a[][]
,不去指定第二维的数据,那么相当于你只是给出了这一串元素的开头地址,系统无法知道几个元素算一组,也就没有了二维的概念
解决方法
1,使用常量限定参数第二维的值
我们在写第二维值的时候不写一个具体的值,而是写一个常量,常量的值我们可以自己设置,所以程序也是有可变形的。对于不同的要求,我们去改常量的值就可以了。但是面对多个不同大小的二维数组时,函数不存在复用性
const int N=3;
void function(int a[][N]){
}
2.使用行指针访问二维数组
这个思路可以为后面打基础,而这个方法的限制与方法一相同
int (*p)[3];//创建一个行指针,类型为int[3]
p = a;//将二维数组a的地址赋值给p
void OutputArray(int (*)p[N],int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
cout<<*(*(p+i)+j);
}
cout<<endl;
}
}
- p+i是一个指针运算,相当于p地址值+i*sizeof(int[3]),运算后结果指向第i行的int[3]类型元素。那么*(p+i)就代表的是第i行的地址,相当于一个[3]大小的一维数组的数组名,这时指向的是第i行第0列的int元素
- 我们在此基础上再做改变:*(p+i)+j,相当于+j*sizeof(int),也就是现在指向了第i行第j列的元素。那么我们对他进行取值,*(*(p+i)+j)就代表了第i行第j列的内容,也就是a[i][j]
3. 转化为一维向量处理
我们也可以认为是使用列指针来访问二维数组
我们前面说过,二维数组的元素在内存中我们可以认为也是一串排列的,第一行后面紧跟着第二行的内容
int *p;//设置一个int类型的指针
p = &a[0][0];//让指针指向数组开头处
void printArray(int *a,int row,int col){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
cout<<a[i*col+j]<<" ";
}
cout<<endl;
}
}
这种方式要求我们计算出二维数组的行数与列数(下文介绍),然后我们在函数中将其作为一维数组处理。
补充:计算二维数组行数列数
我们以int类型的二维数组来距离
- 先分析各个部分
- sizeof(int),返回的是一个int类型元素的长度(所占内存字节数)
- sizeof(array),返回的是整个二维数组的长度(所有元素长度之和)
- sizeof(array[0]),返回的是二维数组中一行的长度(一行中所有元素长度之和)
- sizeof(array[0][0]),返回的是二维数组中一个元素的长度,返回的跟sizeof(int)一样,我们一般用这个,防止类型判断错误
- 利用上述内容得出一下结论
- 数组元素个数:
sizeof(array) / sizeof(array[0][0])
- 数组行数:
sizeof(array) / sizeof(array[0])
- 数组列数:
sizeof(array[0]) / sizeof(array[0][0])
- 数组元素个数:
最终代码
这里只有两个功能:填充数组内容和打印数组
#include<bits/stdc++.h>
using namespace std;
void makeArray(int *a,int row,int col){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
a[i*col+j]=0;
}
}
a[1*col+2]=1;//a[1][2]
a[2*col+3]=2;//a[2][3]
return;
}
void printArray(int *a,int row,int col){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
cout<<a[i*col+j]<<" ";
}
cout<<endl;
}
}
int main(){
int array[11][11];
int row=sizeof(array)/sizeof(array[0]);
int col=sizeof(array[0])/sizeof(array[0][0]);
makeArray(*array,row,col);
printArray(*array,row,col);
return 0;
}
运行结果如下: