在C语言中实现动态分配二维数组

    技术2022-05-11  36

    在C语言中动态的一维数组是通过malloc动态分配空间来实现的,动态的二维数组也可以通过malloc动态分配空间来实现。   实际上,C语言中没有二维数组,至少对二维数组没有直接的支持,取而代之的是“数组的数组”,二维数组可以看成是由指向数组的指针构成的数组。对于一个二维数组p[i][j],编译器通过公式*(*(p+i)+j)求出数组元素的值:   1、p+i 计算行指针。   2、*(P+i) 具体的行,是一个指针,指向该行首元素地址。   3、*(P+i)+j 得到具体元素的地址。   4、*(*(p+i)+j) 得到元素的值。   基于上述原理,我们可以通过分配一个指针数组,再对指针数组的每一个元素分配空间实现动态分配二维数组。   实现   下面是本人写的一个动态分配二维数组的实现,适用于任何类型的二维数组,可以直接使用。   类型定义和错误代码 typedef unsigned char MK_Byte;#define SUCCESS 0 /*No error*/#define MFAILED 1 /*General failure*/#define MNOMEMORY 2 /*Out of memory*/声明//确保初始化#define DeclareTwoDArray(ATYPE, iname) ATYPE ** iname = NULL//定义自己的malloc和free,确保内存正确操作#define MKMALLOC(nsize) malloc(nsize)#define MKFREE(name) /if (NULL != name)/free(name);/name = NULL   实现 int MKCreatArray(int nsize, int X, int Y, void *** parray){ void ** tdarray = NULL; MK_Byte * tmparray = NULL; int i = 0; *parray = NULL; //分配指针数组 if (!(tdarray = (void **)MKMALLOC(sizeof(MK_Byte *) * Y))) {  return MNOMEMORY; } //分配实际数组空间 if (!(tmparray = (MK_Byte * )MKMALLOC(nsize * (X * Y)))) {  MKFREE(tdarray);  return MNOMEMORY; } //初始化内存 memset(tmparray, 0x00, nsize * (X * Y)); //指针数组赋值 for (i = 0; i < Y; i++)  tdarray[i] = (tmparray + (i * X) * nsize); *parray = tdarray; return SUCCESS;}void MKFreeArray(void *** parray){ if (*parray) {  MKFREE((*parray)[0]);  MKFREE((*parray)); }}   使用 void testTwoDArray(){ //声明数组 DeclareTwoDArray(int, a); DeclareTwoDArray(float,b); //创建整型数组 MKCreatArray(sizeof(int), 3, 2, &a); a[1][2] = 10;  a[0][1] = 23;  printf("%d,%d/n",a[1][2],a[0][1]); //使用完一定要FREE MKFreeArray(&a); //重新分配数组 MKCreatArray(sizeof(int), 6, 6, &a); a[5][5] = 234; a[4][0] = 567; printf("%d,%d/n",a[5][5],a[4][0]); MKFreeArray(&a); //创建浮点数组 MKCreatArray(sizeof(float),2,2,&b); b[0][0] = 0.5f; b[1][1] = 0.006f; printf("%g,%g/n",b[0][0],b[1][1]); MKFreeArray(&b);}

     ----------------------------------------------------------------------

    其他讨论:

    摘自:动态二维数组如何定义?

    我在程序中需要使用一个动态的二维数组,行和列的值都需要传入。我在程序中使用了如下的方法:  #include  "malloc.h"  ...  double  *t,**y;  t=(double  *)calloc(r*c,sizeof(double));    //r,c是传入的行和列的值  y=(double  **)calloc(r,sizeof(double  *));  for(int  i=0;i<r;i++)  y[i]=&t[c*i];  ...  结果在编译时没有问题,但运行时就回产生一个内存使用错误。  希望大家能够帮忙解决一下,或者有其他的解决方法也可以。谢谢!  ---------------------------------------------------------------   可以这样使用二维数组:   假设前面已经定义了r行  和  c列   /*指向座标为(x,y)的单元的指针*/  #define  M_pV(pHead,  x,  y)  (pHead+c*y+x)   double  *pArray=(double*)malloc(r*c*sizeof(double));   到时候可以这样用:  *M_pV(pArray,  1,  2)=9;  double  temp=*M_pV(pArray,  1,  2);  ---------------------------------------------------------------   用MFC的CArray模板为例,你也可以使用STL的vector等  做一个2维的动态int数组   typedef  CArray<int,int>  INTARRAY;  typedef  CArray<INTARRAY,INTARRAY>  Int2DArray;  ---------------------------------------------------------------   一个二维数组,其实可以用一个一维指针来访问的。  如:int  iMatrix[10][10];         int  *piMatrix;         piMatrix  =  iMatrix;    //数组名就是数组首地址  那么就有  *piMatrix[2*10+3]  =  iMatrix[2][3]  所以定义一个一维指针就可以了  int  piMatrix;  piMatrix  =  (int*)malloc(r*c*sizeof(int));  for  (i=0;i<r;i++)     for(j=0;j<c;j++)         piMatrix[i*r+j]  (当然,也可以定义一个2维数组,跟Kevin_qing()一样)

    --------------------------------

    摘自:动态分配二维数组的若干方法

    动态分配二维数组的若干方法     动态分配二维数组,方法很多,在这里我说一下我想到的。针对二维数组两  个维的不同,可用不同的方法处理。   一、两维都固定:     这种是最简单,如下:      //  有点困惑的方法:     int  (*a)[M][N];                          //  M、N  为常量     a  =  new  int[1][10][20];          //  为什么要这样呢?     delete[]  a;      //  typedef  法,但一样的困惑     typedef  int  array_two[10][20];     array_two*  a  =  new  array_two[1];  //  还是多了“一维”     delete[]  a;     唉,这个有点失败,使用时还要这样:(*a)[m][n],或者  a[0][m][n],这  还是二维的吗?没办法,只有另想办法了。      //  退一步,声明似乎少了一维    TYPE_1     int  (*a)[N];     a  =  new  int[M][N];     a[var_m][var_n]  =  0;     delete[]  a;     这样似乎不错,只是在声明时却少了一维,但使用起来简单,形式一样。   二、只有一维固定:     如果只有一维固定,分两种形式:[M][n]  和  [m][N],以后者较简单。对于    N  固定的,我们只要这样就可以了:      //  [m][N]  型                                TYPE_2     int  (*a)[N];     a  =  new  int[m][N];     a[var_m][var_n]  =  0;     delete[]  a;     这个看起来与  TYPE_1  很相似,比较二维数组作为函数的参数传递时,第一  维也是不重要的。看一下  new,出来的类型都是  int  (*)[N]。     对于  [M][n]  这种,能过把下标交换一下,就可以利用  TYPE_2  这种了,确  实是不错。如果坚持用  [M][n]  的话,看一下有什么方法。      //  [M][n]  型,直接的方法        TYPE_3     int*  a[M];     for  (int  i  =  0;  i  <  M;  ++i)         a[i]  =  new  int[n];     a[var_m][var_n]  =  0;     for  (int  i  =  M;  i  >  0;)         delete[]  a[--i];     事实上,我们可以改进一下,只用一次  new:      //  [M][n]  型,改进                            TYPE_4     int*  a[M];     a[0]  =  new  int[M*n];     for  (int  i  =  1;  i  <  M;  ++i)         a[i]  =  a[i-1]  +  n;     a[var_m][var_n];     delete[]  a[0];     这样改进的好处是,减少  new  所带来的固有开销;如果失败,无需对前面  已分配的再  delete[]。当然,如果内存比较碎的话,那就没办法了。   三、二维都是动态确定:     二维都是动态确定的话,可以这样:      //  [m][n],直接的方法                      TYPE_5     int**  a;     a  =  new  (int*)[m];     for  (int  i  =  0;  i  <  m;  ++i)         a[i]  =  new  int[n];     a[var_m][var_n]  =  0;     for  (int  i  =  m;  i  >  0;)         delete[]  a[--i];     delete[]  a;     类似改进  TYPE_3,我们也可以将  TYPE_5  改进:      //  [m][n],改进                                  TYPE_6     int**  a;     a  =  new  (int*)[m];     a[0]  =  new  int[m*n];     for  (int  i  =  1;  i  <  m;  ++i)         a[i]  =  a[i-1]  +  n;     a[var_m][var_n]  =  0;     delete[]  a[0];     delete[]  a;     好了,这就是我所想到的办法,当然你可以  std::vector  来搭建二维数组,  只是效率似乎没人满意。实际上,可以只分两种情况:最后一维确定,或不确定。  最后一维确定,只需一次分配;否则,一般要两次。  ---------------------------------------------------------------   //  [M][n]  型,改进                            TYPE_4     int*  a[M];     a[0]  =  new  int[M*n];     for  (int  i  =  1;  i  <  M;  ++i)         a[i]  =  a[i-1]  +  n;     a[var_m][var_n];     delete[]  a[0];  这里似乎有些问题,是不是应该改成a[i]  =  a[i-1]  +  sizeof(int)*n;  ---------------------------------------------------------------   有价值。  up  ---------------------------------------------------------------   up  ---------------------------------------------------------------   int  (*a)[M][N];                          //  M、N  为常量  a  =  new  int[1][10][20];          //  为什么要这样呢?   这里的a不应该是一个三维数组吗?不知道是楼主弄错了还是我理解得不对?  另外,用vector来构建二维数组我觉得没有什么不好,不知道为什么楼主认为效率不令人满意?  ---------------------------------------------------------------   楼上的意见我认可  *a[][]逻辑上已经是三维了   至于你的typedef  int  array_two[10][20];     array_two*  a  =  new  array_two[1];  //  还是多了“一维”  这样定义了  array_two本身是二维数组,定义它的指针也应该是首先分配的是二维数组指针的空间       typedef  定义对象指针  有一个好处就是new的时候不会调用构造函数   class  Object{...  }   typedef  Object*  OFun[1];  OFun  =  new  Object[1];  ---------------------------------------------------------------   学习...  ---------------------------------------------------------------   mark  ---------------------------------------------------------------   int  (*a)[M][N];                          //  M、N  为常量  a  =  new  int[1][10][20];          //  为什么要这样呢?   逻辑上是三维了,感觉就是用起来会方便一点吧,是作为指针来用了,作为一个二维指针,不过自己还没用到过这么困难的东西,看了是不少书,理论也不少了,可还是没实践,学习,  ---------------------------------------------------------------   还有,我最推荐的是TYPE_5,这个东西可以搭建的就不只是m*n的数组了,而是一堆大小不同的一维数组的集合

    ------------------------------

    摘自:动态申请二维数组

               //  allocate  memory             p  =  (int**)malloc(row_x  *  sizeof(int*));             for  (i=0;  i<row_x;  i++)             {                         p[i]  =  (int*)malloc(row_y  *  sizeof(int));             }                          //  use  them             for  (i=0;  i<row_x;  i++)                         for  (j=0;  j<row_y;  j++)                                     p[i][j]  =  i+j;                          //  free  allocated  memory             for  (i=0;  i<row_x;  i++)             {                         free(p[i]);             }             free(p);


    最新回复(0)