在C语言中,一般给函数传递一维数组的参数时,那个参数一般直接声明为一个指针!而且我一直觉得数组名其实是一个常量指针,就是这个指针所指向的地址不能改变!但是我今天刚刚发现,这在多维数组里面是完全不同的!
为什么呢,因为多维维数组有一个特性,就是多维数组做参数的时候,一定要指定除了第一个长度之外的其他长度!我有一个二维数组array[3][4],如果我要传递给函数func(),那么func()的函数原型应该这样定义:
int func(int arr[][4]); //正确 int func(int *arr[4]); //正确
而这样定义则是错误的:
int func(int **arr); //错误 int func(int arr[][]); //错误
而多阶指针则是不需要指定长度的!
比如下面这个关于二维数组的代码,这个是正确的!
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define COL 3 4 #define ROW 4 5 int func(int aa[][COL]) 6 { 7 int i,j; 8 for(i=0;i<ROW;i++) 9 { 10 for(j=0;j<COL;j++) 11 printf("%d ",aa[i][j]); 12 printf(" "); 13 } 14 } 15 int main(int argc,char *argv[]) 16 { 17 int aa[ROW][COL]; 18 int i,j; 19 20 //赋初值 21 for(i=0;i<ROW;i++) 22 for(j=0;j<COL;j++) 23 aa[i][j] = i+j+2; 24 25 func(aa); 26 27 return 0; 28 }
还有下面这个二阶指针的代码也是正确的:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define COL 3 4 #define ROW 4 5 int func(int **pp) 6 { 7 int i,j; 8 for(i=0;i<ROW;i++) 9 { 10 for(j=0;j<COL;j++) 11 printf("%d ",pp[i][j]); 12 printf(" "); 13 } 14 } 15 int main(int argc,char *argv[]) 16 { 17 int **pp; 18 int i,j; 19 20 pp = (int **)malloc(sizeof(int *)*ROW); 21 for(i=0;i<ROW;i++) 22 { 23 pp[i] = (int *)malloc(sizeof(int)*COL); 24 } 25 26 for(i=0;i<ROW;i++) 27 for(j=0;j<COL;j++) 28 pp[i][j] = i+j+2; 29 func(pp); 30 31 for(i=0;i<ROW;i++) 32 { 33 free(pp[i]); 34 } 35 free(pp); 36 return 0; 37 }
但是有一点,就是这两个一定不能混着用!否则除了问题你都不知道去哪里找!比如下面这段代码:
1 #include<stdio.h> 2 #define COL 3 3 #define ROW 4 4 int func(int **pp) 5 { 6 int i,j; 7 for(i=0;i<ROW;i++) 8 { 9 for(j=0;j<COL;j++) 10 printf("%d ",pp[i][j]); 11 printf(" "); 12 } 13 } 14 int main(int argc,char *argv[]) 15 { 16 int pp[ROW][COL]; 17 int i,j; 18 19 for(i=0;i<ROW;i++) 20 for(j=0;j<COL;j++) 21 pp[i][j] = i+j+2; 22 func(pp); 23 24 return 0; 25 }
这里我定义了一个二维数组,但是当作指针传进去了,然后我用的gcc给我这样一个警告(vc++6.0是当做错误来对待的)!
警告传递的参数不对劲!
如果觉得这个警告碍眼,可以直接加一个强制类型转换,就把警告去了!针对上面那个代码就是把第22行改成下面这种形式:
func((int **)pp);
然后编译和运行的结果如下:
然后,我只能说,恭喜你,哥们,你的代码成功地进入了一种让你抓狂的状态!
Ok,上面仅仅是开个玩笑,这里还是要强调一遍,指针和数组不一样,真的不一样,尤其是多维数组和多维指针,传递参数的时候千万不能混了!
================================================
2014.11.21更新
这两天在和别人讨论的时候,突然对这个东西有了更多的体会!
那个二维数组做参数的时候声明长度的用意是什么,其实不就是要划定这个函数能够访问的内存空间的长度!而实现同样功能的二阶指针就不需要来划定这么一个空间!以前我们常讲,C语言的特性就是对于程序员比较信任,给予程序员较高的自由度,同时,这种较高的自由而导致的错误也得由程序员来解决!那么这个特性体现在哪里,我感觉就体现在C语言的核心(这里我用了核心这个词,而没有用灵魂这个词,我感觉C语言的灵魂更像是函数!它代表了将功能打包成模块,然后逐级调用!这正是面向过程思想的体现!),指针上面!上面就是一个很好的例子,数组需要声明访问的内存长度,而指针却不需要,这就说明指针具有较高的自由度,也是C语言给予程序员较高自由度的体现!