二维数组名作形参

原创 2015年04月17日 22:40:39

之前帮同学调一个程序的时候遇到的,把二维数据改为全局变量,不通过参数传递就没问题了,否则程序崩溃。

细究一下,二维数据名用于形参时需要注意哪些方面。

测试程序如下:

#include<stdio.h>
#include<stdlib.h>

void print1(int **a, int m, int n);
void print2(int (*a)[2], int m, int n);

int main()
{
  int a[2][2]={1,2,3,4};
  print1((int**)a,2,2);
  print2(a,2,2);
  system("pause");
  return 0;
}

void print1(int **a, int m, int n)
{
  for(int i=0;i<m;++i)
    for(int j=0;j<n;++j)
    {    
      printf("%d\n",*(a+i*n+j));
      //printf("%d\n",a[i][j]); 
    }
}

void print2(int (*a)[2], int m, int n)
{
  for(int i=0;i<m;++i)
    for(int j=0;j<n;++j)
    {
      printf("%d\n",a[i][j]);        
    }     
}
程序可以正常运行,而且没问题。有问题的是print1中注释掉的语句。可能很多人会觉得二维数组的数组名不就是一个二维指针吗,为什么用a[i][j]的方式访问不行?注释掉的语句在执行时,程序崩溃。

原因是这样的,二维数组的数组名其实是一个int (*)[N]的指针,和 int** 指针还是不一样的。直观来看,对前者一次解引用的话,得到的是数组;对后者一次解引用,得到的是指针。其实在调用的时候就可以发现,如果你不进行强制类型转换,而直接进行这样的调用 print1(a,2,2); 会提示如下错误:cannot convert `int (*)[2]' to `int**' for argument `1' to `void print1(int**, int, int)' 。编译器已经告诉你,类型不匹配了;这个时候你应该想到的是用第二种方式来定义函数。而有的人可能觉得既然类型不匹配,就给直接强制类型转换了,结果编译通过了,但程序崩溃了,更找不出问题。

产生这个问题的根本原因是,对数组名和指针的细微差别没有认识到。

数组名,在访问元素时,是直接取址的过程。比如a[i],它是直接在a的地址上进行一个 i (乘以a[i]的类型大小)的偏移。(每个符号的地址在编译时可知

指针,访问元素时,是一个间接寻址的过程。比如对int *a; 在a[i]取元素时,首先它会在变量a的地址上取数,取得的值作为地址再去寻址,然后再进行一个 i (乘以类型大小)的偏移。

这样的话,对上面测试代码而言,在main函数中,你声明的a是数组名,即int (*)[2]类型,传递到print2中,在print2函数中用a[i][j]访问时,是先对形参a进行一个间接寻址,然后直接寻址。而传递到print1中,首先你需要强制转换成int ** 才可以,在print1中用a[i][j]访问时,是对形参a进行间接寻址后,再间接寻址,这样就发生了错误。而在print1中用*(a+i*n+j)的方式则是可以的。

这个和下面这类错误很类似。就是在一个文件中定义了int a[100]; 然后你想在另一文件中使用它,你用了外部声明,但是你声明成了这样: extern int * a; 这样,在访问a数组的元素时,本来应该是按照数组名的直接寻址方式,在这个文件中却会用指针的间接寻址,就会出现不可预知的错误。

也有参考这里

关于指针和数组名在什么情况下不同,以后有时间再总结下。

关于二维数组传参做形参

二维数组的存储方式是和一维数组没什么区别,但是用二维数组做参数,它的形参该怎样写?要注意的是:函数中的形参其实就相当于一个声明,并不产生内存分配,形参的目的就是要让编译器知道函数参数的数据类型。 正...

二维数组名如何作为参数传递

在用二维数组名作为参数传递时容易出现Segmention Error。这是因为不能正确为二维数组中元素寻址的问题,正确的方法如下: [cpp] view plaincopy ...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

关于二维数组做函数参数,传递形参的形式的问题

数组作为参数进行传递,不能将数组的所用元素一次全都传进子函数中, 要么我们可以一次传进去数组中一个元素的内容,要么我们可以传一个数 组的指针,传递一维数组的指针这里不讲,只说一下传递二维数组时,二...

二维数组作为函数的实参,定义函数形参的方法

最近讨论了一个关于二维数组做为实参传入到函数中,可以定义函数形参的方法,觉得收获挺大,总结如下: 开始时,讨论了几种方法: 1、直接用二维数组的形式,如:int array[3][4]。 ...

c语言中,二维数组作为形参在函数之间的传递

以前经常在函数中传递一维数组或指针。今天,由于工作需要,需要将一个二维数组通过函数来进行传入,原本以为在函数接口处定义一个指向指针的指针就可以了,但是,在编译过程中发现怎么也编译不通过。经过调整,得出...

用行指针为函数形参来实现对该二维数组求最大值

注意:二维数组名是行指针 /* 定义一个二维数组,写函数来实现对该二维数组求最大值。 (要求,用行指针为函数形参) */ #include using namespace std; ...

C语言二维数组作为形参传值问题

题目:编写函数void exchange(int a[M][N]),将MxN维的矩阵中最大元素和最小元素所在的列进行互换,如果最大元素与最小元素在同一列,则不要求互换。 要求:在主函数中初始化原始矩...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二维数组名作形参
举报原因:
原因补充:

(最多只允许输入30个字)