函数的二维数组和二阶指针参数

  在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语言给予程序员较高自由度的体现!

原文地址:https://www.cnblogs.com/bwangel23/p/4108841.html