将一维数组声明为函数的形参,在函数的形参列表中,可以让数组的括号为空。例如,一个以一维数组为形参的函数原型可以用以下语句声明:
void process1DArray(int[]);
一个二维数组的行数(由二维数组的第一个下标指定)不是必需的,
而列数(由第二个下标指定)是必需的。例如,以下这个函数原型声明表示函数有一个二维数组参数,其列数由整型常量SIZE指定:
void process2DArray(int[][SIZE]);
编译器用这个形参中的二维数组的列数来确定元素的位置(在内存中)。对二维数组来说,每一行是一个一维数组。要找到某个特定行中的元素,编译器必须准确地知道每一行有多少个元素,然后才能在访问数组时跳过确切数目的内存单元。
二维数组做函数参数的问题
C语言中,对多维数组的传递,有些捉襟见肘。这是由于C的低级性导致的。理解了数组名、地址、指针的概念以及C是怎么样实现的时候,就能明白了。^_^,这还真是C中的难点。
这些东西在《C专家编程》中有非常详细的说明。
问题是这样的:
实参:你传递给参数的实参是一个二维数组的数组名,也就是二维数组的首地址。
形参:是一个指针的指针。
<查阅一下用数组名定位数组元素和用指针定位元素的不同>;
为了说明问题,不妨把你的形参重新定义成s。所以,在函数的内部,把s处理成指针(注意,不是数组名了!问题就出在这里)。因为s是指针(一个指针的指针)了,所以s[i]就被解释为*(s+i)。看到了吗?这里,函数就无法“正确”(指和我们头脑想的一样)确定步长了。因为s是指针的指针,所以,i的步长被解释为一个指针的大小,自然和你的二维数组的一维大小是不一样的了。这是第一个错误的原因。
第二个错误的原因是因为编译器处理指针和处理数组存在本质的区别。看看我的例子程序,对于数组,data+1和*(data+1)的值是一样的,而对于指针,就严格的“指”过去了。这是因为,数组名,不过是个名字,是个地址。而指针则是个变量。这个在《C专家编程》中有详述,我就不多说了。例子如下:
[yangwl:/home/users50/yangwl/test/data]$ cat test.c
#include <stdio.h>;
#include <stdlib.h>;
void fun(char **data);
int main(void)
{
char data[2][5];
printf("in main\n");
printf("data:%p\n", data);
printf("*data:%p\n", *data);
printf("data+1:%p\n", data+1);
printf("*(data+1):%p\n", *(data+1));
printf("data[1]:%p\n", data[1]);
printf("&data[1][3]:%p\n", &data[1][3]);
fun(data);
exit(0);
}
void fun(char **data)
{
printf("in fun\n");
printf("data:%p\n", data);
printf("*data:%p\n", *data);
printf("data+1:%p\n", data+1);
printf("*(data+1):%p\n", *(data+1));
printf("data[1]:%p\n", data[1]);
printf("&data[1][3]:%p\n", &data[1][3]);
return ;
}
[yangwl:/home/users50/yangwl/test/data]$ gcc test.c
test.c: In function `main':
test.c:17: warning: passing arg 1 of `fun' from incompatible pointer type
[yangwl:/home/users50/yangwl/test/data]$ ./a.out
in main
data:0xbffffbd0
*data:0xbffffbd0
data+1:0xbffffbd5
*(data+1):0xbffffbd5
data[1]:0xbffffbd5
&data[1][3]:0xbffffbd8
in fun
data:0xbffffbd0
*data:0x4212aa58
data+1:0xbffffbd4
*(data+1):0x4212a2d0
data[1]:0x4212a2d0
&data[1][3]:0x4212a2d3
[yangwl:/home/users50/yangwl/test/data]$
所以,用到传递参数的时候,尽量不要传递多维数组。需要传递的时候(一般也就是字符串数组),建立一个指针数组对应,然后传递。对于整“块”的多维数组,谨慎的使用全局量好了。
^_^,偶也是理解了好长时间呢。《C专家编程》上面专门有一章讲这个问题。偶看人家讲的挺好的。我也不能表述的更清楚。还是去看看书吧,呵呵,这书写的真的很不错。
总之就是:数组无法作为参数,总会被编译器将地址赋值给形参指针的,即使指针定义成数组形式,也还是指针。然后各种差别都是由数组和指针不同的定位元素的方式导致的。
初学的时候,总是听说,数组和指针是一回事。而学到细节,就一定要再次区分开数组和指针了。偶觉得,数组和指针这两个概念从分到合再到分的过程就是一个进步的过程。