二维数组名作为形参的传递问题(不知大家有没有更好的解决方法)

39 views
Skip to first unread message

孟阿龙

unread,
Apr 3, 2009, 10:11:32 AM4/3/09
to zlg_c
最近写c程序时才发现之前的c语言确实没学扎实啊,一个简单的二维数组名作为参数传递的问题都花了好长时间才解决。
以下是一个简单的测试程序:
通过调用一个函数InitArray(int **array)初始化一个二维数组
1 #include <stdio.h>
2 #define ROW 3
3 #define COL 3
4 void InitArray(int **Array);
5 int main()
6 {
7 int i,j,Array[ROW][COL];
8 int *p[ROW];
9 for(i=0;i<ROW;i++)
10 {
11 p[i]=Array[i];
12 }
13 InitArray(p); /*注释一*/
14 /*InitArray((int **)Array);*/ /*注释二*/
15 for(i=0; i<ROW; i++) /*打印数组内容*/
16 {
17 printf("\n");
18 for(j=0; j<COL; j++)
19 {
20 printf("%d ",Array[i][j]);
21 }
22 }
23 return 0;
24
25 }
26 void InitArray(int **Array)
27 {
28
29 int i,j,k=0;
30 for(i=0; i<ROW; i++)
31 for(j=0; j<COL; j++)
32 {
33 printf("input your %dth number:",++k);
34 /* scanf("%d",&Array[i][j]); */ /*注释三*/
35 scanf("%d",(Array+COL*j+i)); /*注释四*/
36 }
37
38 }


用gcc编译后出现警告
maan.c: 在函数‘InitArray’中:
maan.c:35: 警告: 格式‘%d’需要类型‘int *’,但实参 2 的类型为‘int **’
运行当执行打印数组时出现错误
input your 1th number:1
input your 2th number:2
input your 3th number:3
input your 4th number:4
input your 5th number:5
input your 6th number:6
input your 7th number:7
input your 8th number:8
input your 9th number:9

0 0 0
-1080424648 -1209541106 -1208825479
段错误

这是因为系统无法确定具体的地址。


当采用注释二和注释四搭配时编译出现警告

maan.c: 在函数‘InitArray’中:
maan.c:35: 警告: 格式‘%d’需要类型‘int *’,但实参 2 的类型为‘int **’
但是可以执行成功结果为:

input your 1th number:1
input your 2th number:2
input your 3th number:3
input your 4th number:4
input your 5th number:5
input your 6th number:6
input your 7th number:7
input your 8th number:8
input your 9th number:9

1 4 7
2 5 8
3 6 9


如果调用InitArray(int**Array)函数时直接传入二维数组名而不对他进行强制转换,那编译将会出现警告(假设该文件名为maan.c)

maan.c: 在函数‘main’中:
maan.c:13: 警告: 传递参数 1 (属于‘InitArray’)时在不兼容的指针类型间转换
maan.c: 在函数‘InitArray’中:
maan.c:34: 警告: 格式‘%d’需要类型‘int *’,但实参 2 的类型为‘int **’

这是指针类型不匹配引起的。但是这个程序却可以正常执行结果为

input your 1th number:1
input your 2th number:2
input your 3th number:3
input your 4th number:4
input your 5th number:5
input your 6th number:6
input your 7th number:7
input your 8th number:8
input your 9th number:9

1 4 7
2 5 8
3 6 9


如果将函数InitArray(int **Array)改为InitArray(int *Array)
编译后结果为

maan.c: 在函数‘main’中:
maan.c:13: 警告: 传递参数 1 (属于‘InitArray’)时在不兼容的指针类型间转换

但是依然可以执行结果为:

input your 1th number:1
input your 2th number:2
input your 3th number:3
input your 4th number:4
input your 5th number:5
input your 6th number:6
input your 7th number:7
input your 8th number:8
input your 9th number:9

1 4 7
2 5 8
3 6 9

当采用采用注释一和注释三搭配时程序可以完全正常执行。

今天同学又给提供了一种方法,如果将注释三和注释四改为scanf("%d",(*(Array+i)+j));则无论用注释一还是注释二均可正常执行。看来还是对二维数组的地址确定问题理解不够。

不知大家有没有更好的解决方法

兰鹏

unread,
Apr 4, 2009, 4:19:41 AM4/4/09
to zl...@googlegroups.com
#include <stdio.h>

#define ROW 3
#define COL 3
void InitArray(int Array[ROW][COL]);
int main()
{
    int i,j,Array[ROW][COL];                                                                                    
    InitArray(Array);

    for(i=0; i<ROW; i++)   /*打印数组内容*/
    {  
        printf("\n");
        for(j=0; j<COL; j++)
        {  
            printf("%d ",Array[i][j]);
        }  
    }  
    printf("\n");
    return 0;

}
void InitArray(int Array[ROW][COL])
{

    int i,j,k=0;
    for(i=0; i<ROW; i++)
        for(j=0; j<COL; j++)
        {  
            printf("input your %dth  number:",++k);
            scanf("%d",&Array[i][j]);
        }  
}
这样就可以了。
对了,你既然是C助学团的成员就不需要和我联系了。好好的带领大一的学习c语言吧。你能分析这样一个程序,你的C语言很厉害啊。
 发送时间 星期六 下午2:25

2009/4/3 孟阿龙 <boya...@gmail.com>

孟阿龙

unread,
Apr 6, 2009, 8:06:13 AM4/6/09
to zl...@googlegroups.com
看来我是把简单问题复杂化了,兰鹏的这个方法相比要简单多了,我还得多多学习啊

就是不知在函数void InitArray(int Array[ROW][COL]);中的形参是什么类型的,是int型还是指针类型的?

林文彬网络0802

unread,
Apr 8, 2009, 2:51:25 AM4/8/09
to 周立功C语言俱乐部
有人曾经这样形容过数组名,指针常量(think C++的作者, 朱洪也曾经提起过) 因为数组名就是该数组的首地址
在C中有这样的等价关系:
int a[3][3];
a[2][1]; <=> *(*(a + 2) + 1);
int a[3];
a[2]; <=> *(a + 2);
所以你的形参即是二维数组 也是 二维指针

林文彬网络0802

unread,
Apr 8, 2009, 3:16:42 AM4/8/09
to 周立功C语言俱乐部
还有当出现错误的提示说地址错误而你有用到指针的时候
较好的查错是输出每次用到指针的地址然后对比
最好是直接使用 断言 ,检查是否指针越界
百度一下 断言

其实,一种好的编程习惯是使用大量的断言,

On 4月6日, 下午8时06分, 孟阿龙 <boyan1...@gmail.com> wrote:

林文彬网络0802

unread,
Apr 8, 2009, 3:19:35 AM4/8/09
to 周立功C语言俱乐部
你没有复杂化,因为很多时候我们必须用一维数组实现二维数组
看看数据结构(清华出版的) 我忘记第几页了...貌似是稀疏矩阵那里有讲到

On 4月6日, 下午8时06分, 孟阿龙 <boyan1...@gmail.com> wrote:

林文彬网络0802

unread,
Apr 8, 2009, 3:11:02 AM4/8/09
to 周立功C语言俱乐部
说实话 你这样写本来应该报错而不是警告 我用 //在后面对里面的问题做一些说明

On 4月3日, 下午10时11分, 孟阿龙 <boyan1...@gmail.com> wrote:
> 最近写c程序时才发现之前的c语言确实没学扎实啊,一个简单的二维数组名作为参数传递的问题都花了好长时间才解决。
> 以下是一个简单的测试程序:
> 通过调用一个函数InitArray(int **array)初始化一个二维数组
> 1 #include <stdio.h>
> 2 #define ROW 3
> 3 #define COL 3

> 4 void InitArray(int **Array); //首先这是一种不良的风格,应该写成 void InitArray(int Array[][]);
> 5 int main()
> 6 {
> 7 int i,j,Array[ROW][COL]; //二维数组名准确的来说属于 行指针的一种 行指针每加1是跳一行的 也就是说 Array + 1 等于Array第二行的首地址
> 8 int *p[ROW]; //数组指针


> 9 for(i=0;i<ROW;i++)
> 10 {
> 11 p[i]=Array[i];
> 12 }

> 13 InitArray(p); /*注释一*/ //注意 你传递的是数组指针


> 14 /*InitArray((int **)Array);*/ /*注释二*/
> 15 for(i=0; i<ROW; i++) /*打印数组内容*/
> 16 {
> 17 printf("\n");
> 18 for(j=0; j<COL; j++)
> 19 {
> 20 printf("%d ",Array[i][j]);
> 21 }
> 22 }
> 23 return 0;
> 24
> 25 }
> 26 void InitArray(int **Array)
> 27 {
> 28
> 29 int i,j,k=0;
> 30 for(i=0; i<ROW; i++)
> 31 for(j=0; j<COL; j++)
> 32 {
> 33 printf("input your %dth number:",++k);
> 34 /* scanf("%d",&Array[i][j]); */ /*注释三*/

> 35 scanf("%d",(Array+COL*j+i)); /*注释四*/ // 如果按你的意思 就是用注释一 那么你这里的... 我都不知道你为什么要这要写
> 36 } //你每加一他就跳到你指针数组的下一个元素 是指针中的下一个元素 而不是Array数组中的元素
> 37 //貌似你定义的指针数组只有三个元素诶, 你加那麽多干嘛, 正确的应该是 *(Array + j) + i;
> 38 } //顺便说一下, 对于二维数组名即行指针 Array + j 是跳到 第j行的首地址

> 今天同学又给提供了一种方法,如果将注释三和注释四改为scanf("%d",(*(Array+i)+j));则无论用注释一还是注释二均可正常执行。看来还-是对二维数组的地址确定问题理解不够。
>
> 不知大家有没有更好的解决方法

孟阿龙

unread,
Apr 9, 2009, 4:31:34 AM4/9/09
to zl...@googlegroups.com
恩,学习中....

陈百虎

unread,
Apr 16, 2009, 10:28:01 AM4/16/09
to 周立功C语言俱乐部
二维数组和二维指针还是有很大的区别的!

> > 就是不知在函数void InitArray(int Array[ROW][COL]);中的形参是什么类型的,是int型还是指针类型的?- 隐藏被引用文字 -
>
> - 显示引用的文字 -

Reply all
Reply to author
Forward
0 new messages