为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

[精彩]二维数组传参传值

2018-02-05 14页 doc 32KB 12阅读

用户头像

is_963767

暂无简介

举报
[精彩]二维数组传参传值[精彩]二维数组传参传值 二维数组传参||传值 先给出问题: 像下面这样的数组,在函数中如何传参,也就是说如何保证虚参与实参类型一致。 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); ...
[精彩]二维数组传参传值
[精彩]二维数组传参传值 二维数组传参||传值 先给出问题: 像下面这样的数组,在函数中如何传参,也就是说如何保证虚参与实参类型一致。 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 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.out yes no uncertain yes no unsure [root@localhost ansi_c]# 如果将 func1(str_arr); func2(str_array); 改成: func1(str_array); func2(str_arr); 会怎么呢, [root@localhost ansi_c]# gcc test.c test.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 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.out yes no uncertain yes no unsure [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 int main() { int array[3][4]; int **p = array; } **********************************/ root@localhost ansi_c]# gcc test2.c test2.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 void fun( int *a, int m, int n) { int i,j; for( i=0; i void f( char **a, int n) { int i; printf("%c/n",*( (char*)a+0 ) ); printf("%c/n",((char * )a)[n] ); puts("------------OK"); for(i=0;i<3;i++) printf("%s/n",(char*)a+i*n ); } int main() { char str_arr[3][10] = {"yes","no","uncertain"}; f( (char **)str_arr, 10); return 0; } /****************end*************************/ 运行结果: [root@localhost ansi_c]# ./a.out y n ------------OK yes no uncertain [root@localhost ansi_c]# 这里也做了强制类型转换,转换成字符指针, printf("%s/n",(char*)a+i*n ); 每个字符串的地址就是数组中字符'y'、'n'、'u'的地址, printf("%c/n",*( (char*)a+0 ) );字符在数组中的排列是顺序的,可以用 *( (char*)a+i )或 ((char * )a)[i] 表示。 当然这个程序也可以改成这样,完全不用二级指针: /*****************************************************************/ #include void f( char *a, int n) { int i; printf("%c/n",*( a+0 ) ); printf("%c/n",(a)[n] ); puts("------------OK"); for(i=0;i<3;i++) printf("%s/n",a+i*n ); } int main() { char str_arr[3][10] = {"yes","no","uncertain"}; f( (char *)str_arr, 10); return 0; } /*****************************************************************/ 归根结底,还是把它转成一级指针来用。 下面做个小结: 数组传参 数组: int array[4][10]; 函数原型: void func1( int a[][10] ); void func2( int (*a)[10] ); void func3( int *p, int col, int row ); 函数调用: func1( array ); func2( array ); func3( (int *)array, 4, 10 ); 容易出错的地方: int arr[][10]; int **p = arr; 这种方式是错误的. 应该是 int (*p)[10] = arr; 同理,也不能将arr传给fun( int **p) 另外数组传参之后会降级为指针,如: #include void Test(char a[][2]) { int size = sizeof( a );//4 } int main(void) { char a[3][2] = {'a','b','c','d','e','f'}; int size =sizeof( a );//6 Test( a ); return 0; } 来源: 函数原型:要求传入一个动态二维数组 void func1(int **p,int row, int column) { } 调用: int main() { int m,n; int **b; cin >> m; cin >> n; b = new int *[m]; for(int i=0; i
/
本文档为【[精彩]二维数组传参传值】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索