二维数组作为参数的函数的定义及调用方法

二维数组作为参数的函数的定义及调用方法

Geophoenix

C语言编程的过程中,不可避免的会碰到二维或二维以上的数组作为函数的形参的情况,在以前的编程过程中,习惯了动态数组的应用,很是使用直接定义高维数组。最近在编程的过程中就碰到了这个问题:有如下的测试程序:

voidtest(double  **x,int Row,int Col);

voidtest(double  **x)

{

         for(int i=0;i<Row;i++)

                   for(int k=0;k<Col;k++)

                            x[i][k] += 100.0;

}

intmain(int argc, char *argv[])

{

/*

         double **x;

        x = new double *[3];

        for(int i=0;i<3;i++)

         x[i] = new double[3];

*/

    double x[3][3];

         for(int i=0;i<3;i++)

                   for(int k=0;k<3;k++)

                            x[i][k] = i*k;

         test(x,3,3);

         for(int i=0;i<3;i++)

                   for(int k=0;k<3;k++)

                            printf("x[%d][%d]= %e\n",i,k,x[i][k]);

        getch();

         return 0;

}

编译时提示Cannot convert 'double [*][3]' to double **'。

将调用方式强制进行类型转换:test((double **)x),编译通过,运行出错,提示非法越界。

据传:因为栈上分配的数组和堆上分配的数组在内存排列上可能不相同,直接定义的数组是存储在程序的堆栈区,数据占用连续的区间;而动态申请的数组是在系统的远堆上(far heap),除最后一维的元素是连续存放的外,其他维上的元素有可能不是在一块连续的内存区域里

//栈上: 
int   ia[2][2]   = {2,3,4,5};    //4个元素是连续排列的内存段 
//堆上: 
int   **p  =  new  int*[2];   //只有每行内是连续排列,各行并不一定连续排列 
        for ( int  i  = 0;  i  < 2; i++ ) 
        { 
               p[i]   =  new  int[2]; 
        } 
      for ( int  i  =  0;  i  <  2;  i++ ) 
        { 
               for ( int  j  =  0;  j  <  2;  j++ ) 
               { 
                       p[i][j]   =   ia[i][j]; 
               } 
        } 

         所以对栈上的数组用int  **p指向首地址,因为int  **p一次解引用为地址指针,而非堆上的指向数组的指针,所以二次解引用会出错。 
如果找一个通用方程只能用: 
void   f( int  *p, int  row,  int  col )     //给出数组的行和列,对堆上的数组不合适   

        for ( int  i =  0;  i  <  row;  i++) 
        { 
               for ( int  j  =  0;  j  < col;  j++ ) 
               { 
                       cout < < p[i * row + j] < < "   ";                        
               } 
               cout < < endl; 
        } 


int   main(){ 
    //......... 
    int   ia[2][2]   =  {2,3,4,5}; 
    f( (int*)ia, 2, 2 ); 
}

采用上面的通用办法还是比较麻烦,这无形中对编程增加了难度,为了避免这个麻烦可以采用动态数组的形式,将原来采用直接定义的数组全部换成动态数组,类似开头例子中被注释掉的那部分代码,当然这样也有后续的麻烦,动态数组的生命周期完成后必须释放内存空间,这也有点罗嗦,但是毕竟可以直接使用数组的形式,比上面的通用方式还是要简单一点。

         如果执意要使用直接定义的数组该怎么办呢?有如下几种方法:

方法一:


voidtest(double  (*x)[3], int Row, int Col);

调用方式:test(x,Row,Col);

调用用方式 test(x,Row,Col);

方法二:

voidtest(double  x[][3], int Row,int Col);

调用方式 test(x,Row,Col);

         对于多维数组作为参数,除第一维之外的其它维必须指定维数,否则是肯定编译不过去的。

         从上面的对直接定义的数组的引用情况看,直接定义的数组的使用比较麻烦,一旦直接定义数组的维数发生变换,函数的定义必须相应的修改,否则程序就会出错,这也增加了程序进一步开发的麻烦,为了一劳永逸的解决这个问题,建议还是使用动态数组的方法,虽然需要手工释放内存,但是除却了后续的麻烦。

参考来源:http://topic.csdn.net/t/20060714/09/4879614.html

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值