当数组作参数时
C语言中的数组和指针总保持着'千丝万缕'的联系,这里仅针对数组作为函数实参时的情况做些说明^_^。
C语言中的数组可分为一维数组和多维数组两类,而多维数组中又以二维数组最为常见。这里也仅针对这一维数组和二维数组作简要说明。
看过'高质量C++编程指南'的人可能都知道书中有这样一句'注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针',这句话针对一维数组固然是正确的,但是对于多维数组,这显然不完全正确。但是如果你说C语言中的数组默认就指一维数组,那么这也就过得去了。C语言之所以把数组形参当作指针是出于效率考虑,试想如果把一个数组全部拷贝这样势必带来性能上的损失,如果数组很大的话,这种完全拷贝的方法就是不能忍受的了。所以目前无论你在函数声明中像'void func1(char a[])'这样写,还是像'void func1(char *a)',编译器都会把它看成后者的形式,对于一维数组,显然这没什么可说的,但是对于二维数组来说,其中还有不少值得商榷的地方。
C语言中的二维数组可以看作为'数组的数组',而且其采用'行主序',即'最右边的下标'是最先变化的。由于指针和数组的关系导致,二维数组可以广义表示为多种形式:
(1) char a[m][n] — 标准形式;
(2) char *p[n] — 指针数组形式;
(3) char (*p)[n] — 数组(行)指针的形式
(4) char **p — 指针的指针的形式
这些形式虽然都能表示二维数组,但是它们并不等价,这也给参数原型设计带来一定的不便,不过二维数组作为参数后的转化还是有原则可循的,那就是:'数组的数组'被转换为'数组的指针',下面就逐一说说每种形式对应的函数参数原型,通过例子认真体会一番:
(1) char a[m][n] — void func(char (*p)[]); 二维数组退化为数组的指针,关于如何声明数组的指针,可以参见"理解C复杂声明之'优先级规则'"和"C复杂声明解析"两篇文章;
(2) char *p[n] — void func(char **p); 这个是一个指针数组,我们只需要取地址即可;
(3) char (*p)[n] — void func(char (*p)[]); 这个本身就是一个数组指针,原封不动即可;
(4) char **p — void func(char **p); 对于指针的指针类型,同样原封不动。
三维以上的数组不常用,用起来也较复杂,这里不作说明。
评论