当前位置:文档之家› 二维数组传参传值

二维数组传参传值

二维数组传参||传值先给出问题:像下面这样的数组,在函数中如何传参?也就是说如何保证虚参与实参类型一致。

char str_arr[3][10] = {"yes","no","uncertain"};char *str_array[] = {"yes","no","unsure"};函数原型:void func1( char (*a)[10] )void func2( char **a )调用:func1( str_arr );func2( str_array);如果向func2()中传入str_arr会怎么样呢?编译器会警告:传递参数 1 (属于‘func2’)时在不兼容的指针类型间转换。

即虚参与实参类型不一致。

同理,也不能向func1()中传入str_array。

我们给出完整的测试程序:/********二维数组传参测试程序***************/#include <stdio.h>void func1( char (*a)[10]){int i;for(i=0;i<3;i++)printf("%s/n",a[i]);}void func2( char **a ){int i;for(i=0;i<3;i++)printf("%s/n",*(a+i));}int main(){char str_arr[3][10] = {"yes","no","uncertain"};char *str_array[] = {"yes","no","unsure"};char *str[3] = {"a","b","c"};/*这两种表达效果一样*/func1(str_arr);func2(str_array);return 0;}/******************end*******************/运行结果:[root@localhost ansi_c]# gcc test.c[root@localhost ansi_c]# ./a.outyesnouncertainyesnounsure[root@localhost ansi_c]#如果将func1(str_arr);func2(str_array);改成:func1(str_array);func2(str_arr);会怎么呢?[root@localhost ansi_c]# gcc test.ctest.c: 在函数‘main’ 中:test.c:22: 警告:传递参数1 (属于‘func1’)时在不兼容的指针类型间转换test.c:23: 警告:传递参数1 (属于‘func2’)时在不兼容的指针类型间转换这两种数组的正确赋值应该如下:char str_arr[3][10] = {"yes","no","uncertain"};char *str_array[] = {"yes","no","unsure"};char (*pa)[10] = str_arr;char **p = str_array;pa和p才是和他们相一致的类型。

当然,如果不是传参的话,在main()函数中就不会发生这么多烦恼了。

/*************非传参时的情况************************/#include <stdio.h>int main(){char str_arr[3][10] = {"yes","no","uncertain"};char *str_array[] = {"yes","no","unsure"};char *str[3] = {"a","b","c"};int i;for(i=0;i<3;i++)printf("%s/n",str_arr[i]);for(i=0;i<3;i++)printf("%s/n",str_array[i]);return 0;}/*************************************/运行结果:[root@localhost ansi_c]# gcc test1.c[root@localhost ansi_c]# ./a.outyesnouncertainyesnounsure[root@localhost ansi_c]#这说明了一点,在没传参之前,main()函数清楚它们都是二维数组。

对于上面给出的两种函数原型:函数原型:void func1( char (*a)[10] )void func2( char **a )这两种传参方法有什么不同呢?这们对实参有什么要求呢?上面只是抛出了一个问题,我在这里的主题是想搞清楚二维数组传参有什么奥秘,而非只针对这一个问题提出解决方法。

后面从基础的开始讨论。

我们先看看教材上怎么讲这一块的,谭浩强的《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 array[3][4],要传参的话,函数原型可以为下面三种的任一种:void func(int a[3][4])void func(int a[][4])void func(int (*a)[4])调用时为:func(array);同时教材里也说了,如果在型参里不说明列数,则编译器无法决定应为多少行多少列。

那么能不能把int array[3][4]的数组名array 传给void func(int **a)呢?看下面:/**********************************/#include <stdio.h>int main(){int array[3][4];int **p = array;}**********************************/root@localhost ansi_c]# gcc test2.ctest2.c: 在函数‘main’ 中:test2.c:5: 警告:从不兼容的指针类型初始化[root@localhost ansi_c]#虽然从本质上讲int array[3][4] 的数组名相当于二级指针,但它不等同于一般的二级指针,因为它还含有数组相关的信息,所以在main函数中:char str_arr[3][10] = {"yes","no","uncertain"};for(i=0;i<3;i++)printf( "%s/n",str_arr+i );它可以通过下标,每次跳过10个字节来寻址。

我们再看看编译器是怎样处理数组的:对于数组int p[m][n];如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),编译器是这样寻址的:p + i*n + j;我们再看一个例子:/*********************二维数组传参*****************************/#include <stdio.h>void fun( int *a, int m, int n){int i,j;for( i=0; i<m; ++i){for(j=0;j<n;++j){printf("%d ", *( a+i*n+j ) );}putchar('/n');}}void func( int *a, int m, int n){int i,j;for( i=0;i<m*n;++i){printf("%d ",a[i]);}putchar('/n');}int main(){int a[3][3] ={{2, 2, 2},{3, 3, 3}};fun( (int *)a, 3,3);func( &a[0][0],3,3);func( (int *)a, 3,3);return 0;}********************end******************************/ [root@localhost ansi_c]# gcc test4.c[root@localhost ansi_c]# ./a.out1 1 12 2 23 3 31 1 12 2 23 3 31 1 12 2 23 3 3[root@localhost ansi_c]#我们来看其中的要点,数组为:int a[3][3] ={{1, 1, 1},{2, 2, 2},{3, 3, 3}};函数原型和调用为:原型:void fun( int *a, int m, int n){.............printf("%d ", *( a+i*n+j ) ); .............}调用:fun( (int *)a, 3,3);原型:void func( int *a, int m, int n){.............printf("%d ",a[i]);.............}调用:func( &a[0][0],3,3);func( (int *)a, 3,3);我们发现这两种方式都能正常执行,我们把一个二级指针,强制转换成了一级指针传了进去,并在函数中模仿编译器数组的寻址方式:*( a+i*n+j )。

相关主题