目录
2.根据数组的存储原理把二位数组当作一维数组来操作(降维处理)
函数参数传递二维数组的问题
将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。在学编译原理的时候知道编译器是这样处理数组的:
对于数组 int p[m][n];
如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),编译器是这样寻址的,它的地址为:
p + i*n + j;
从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。
这与数据类型类似,试想如果没有数据类型的区别,编译器如何寻址呢?8位的还是16位的?还是32位的?也就是编译器必须要知道它一个单元占多长的内存,至于内训里有多少个单元,是可以不用知道的。
举个形象的例子,这里有一堆苹果,老板让你把他们装起来。试想,你问老板“这总共是多少筐”重要还是问老板“一筐装几个”重要?只要老板告诉你一筐装几个,你管他能装几筐!老板知道就行了,你就不用管了。
在编译一维数组形参的函数原型时,既可以把它写成数组的形式,也可以把它写成指针的形式,但是对于多维数组,只有第一维可以进行如此选择!想要把二维数组形参的函数原型写成下列这种方式是不对的:
void Func(int **array, int m, int n);
解决方案
那问题就来了,我们该怎么传递二维数组参数呢?
总的来说解决方法有两个
1.传递第二维和更高维的大小
既然第二维和更高维度的大小必须指定,那就指定好了。但是既然指定了该函数参数中的二位数组的大小,就要经常根据使用情况对其大小进行修改,所以最好定义为一个宏定义。代码如下
#include <stdio.h>
#define M 4
#define N 6
int A[M][N] = {
{1,2,3,4,5,6},
{7,8,9,10,11,12},
{13,14,15,16,17,18},
{19,20,21,22,23,24},
};
void ArrayPrint(int A[][N], int m, int n);//遍历打印二维数组A[i][j]
int main()
{
ArrayPrint(A,M,N);
return 0;
}
void ArrayPrint(int A[][N],int m,int n)//遍历打印二维数组A[i][j]
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%d\t", A[i][j]);
}
printf("\n");
}
}
此外前文说到,在编译一维数组形参的函数原型时,既可以把它写成数组的形式,也可以把它写成指针的形式,但是对于多维数组,其第一维可以进行如此选择!因此第一维度也可以改为指针:void ArrayPrint(int (*A)[5], int n, int m)
2.根据数组的存储原理把二位数组当作一维数组来操作(降维处理)
前面已经提到,即使是二维数组,其在内存中的存储也是顺序的存储。
对于数组 int p[m][n];
如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),编译器是这样寻址的,它的地址为:
p + i*n + j;
既然这样,我们就也可以通过指针来寻址二维数组。也就是说我们传递一个指向二维数起始内存的指针就可以实现对二维数组的操作,那我们只需要传递一个指向二维数组的首地址的指针就行了。示例代码如下
#include <stdio.h>
#define M 4
#define N 6
int A[M][N] = {
{1,2,3,4,5,6},
{7,8,9,10,11,12},
{13,14,15,16,17,18},
{19,20,21,22,23,24},
};
void ArrayPrint(int* A, int m, int n);//遍历打印二维数组A[i][j]
int main()
{
ArrayPrint(&A[0][0],M,N);
return 0;
}
void ArrayPrint(int *A,int m,int n)//遍历打印二维数组A[i][j]
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%d\t",*(A + i * n + j));
}
printf("\n");
}
}