以下是网上摘抄的一段:
首先,我引用了谭浩强先生编著的《C程序设计》上面的一节原文,它简要介绍了如何将二维数组作为参数传递,原文如下(略有改变,请原谅):
[原文开始]
可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如:
void Func(int array[3][10]);
void Func(int array[][10]);
二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:
void Func(int array[][]);
因为从实参传递来的是数组的起始地址,在内存中按数组排列规则存放(按行存放),而并不区分行和列,如果在形参中不说明列数,则系统无法决定应为多少行多少列,不能只指定一维而不指定第二维,下面写法是错误的:
void Func(int array[3][]);实参数组维数可以大于形参数组,例如实参数组定义为:
void Func(int array[3][10]);
而形参数组定义为:
int array[5][10];
这时形参数组只取实参数组的一部分,其余部分不起作用。
[原文结束]
大家可以看到,将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。大家在学编译原理这么课程的时候知道编译器是这样处理数组的:
对于数组 int p[m][n];
如果要取p[i][j]的值(i>=0 && i<M 0<="j" && j < n),编译器是这样寻址的,它的地址为:
p + i*n + j;
从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,这就难办了,编译器不能识别阿,怎么办呢?不要着急,编译器虽然不能识别,但是我们完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随机的参数,例如:
void Func(int array[3][10]);
void Func(int array[][10]);
变为:
void Func(int **array, int RowSize, int LineSize);
在转变后的函数中,array[i][j]这样的式子是不对的(不信,大家可以试一下),因为编译器不能正确的为它寻址,所以我们需要模仿编译器的行为把array[i][j]手工转变为:
*((int*)array + LineSize*i + j);即把二维数组当作一维数组来处理。
数组作为形参的问题
1 一维数组作为函数形参
数组作为形参时,编译器通常只会检查数组形参关联的实参,检查的项目包括实参是不是指针、指针类型和数组元素的类型是否匹配,但不会检查数组的长度。
void print(int *a[])
void print(int *a[10])
void print(int *a)
以上三个函数的声明是等价的。
在很多情况下,将数组形参直接定义为指针要比使用数组语法定义方便很多。因为定义为指针后,函数可以借助于指针方便的操作数组元素。
数组以非引用类型的传递时,此时数组会自动转换为同类型的指针,即初始化为相应类型实参的副本。
调用函数时,函数实际操作的是指针的副本,而不会修改实参指针的值,但是可以通过指针改变数组元素的值。
2 多维数组的传递
多维数组的元素本身就是数组。
和一维数组一样,多维数组也是以0号元素的指针形式传递。在传递时,必须指定除了第一维以外的所有维的长度,编译器忽略第一维的长度。
void print(int (*matrix)[10],int RowSize)
10为此二维数组第二维的大小,RowSize是第一维的大小。
void print(int matrix[][10],int RowSize)
对二维数组的处理可以采用将二维数组看作一维或者二维数组来处理,下面两个例子分别采用了这两种方法。
例1 将二维数组当作一维数组来处理:
#include "stdio.h"
void print(int *p,int RowSize,int LineSize)
{
int i,j;
for(i=0 ; i<ROWSIZE ; i++ )
{
for(j=0 ; j<LINESIZE ; )
printf("%d ",*(p+i*LineSize+j));
printf("\n");
}
}
void main()
{
int i,j,a[3][3]={ {1,0,0} , {0,1,0} , {0,0,1} };
print( (int *)a ,3,3);
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d ",*(*(a+i)+j));
printf("\n");
}
}
例2 将二维数组依旧当作二维数组来处理
下面是一个字符串数组的参数传递程序,实现将字符串数组中的字符串按照从小到大的顺序进行排序:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void WordSort(char p[][10],int RowSize)
{
int n=0,m;
char temp[10];
for(n=0;n<ROWSIZE-1;++N)
for(m=n+1;m<ROWSIZE;++M)
if( strcmp(p[m],p[n]) < 0 )
{
strcpy(temp,p[n]);
strcpy(p[n],p[m]);
strcpy(p[m],temp);
}
for(n=0;n<5;++n)
printf("%s\n",p[n]);
}
void main()
{
int k=0;
char word[5][10];
for(;k<5;++k)
scanf("%s",&word[k]);
WordSort(word,5);
printf("sorted word:\n");
for(k=0;k<5;k++)
printf("%s\n",word[k]);
system("pause");
}