C/C++中动态申请二维数组的方式

C/C++中动态申请二维数组的方式,测试代码如下:

#include <cstdio>

/*二级指针**作为形参,可以接受二级指针**p、指针数组*p[]作为实参的参数,从而传递二维数组*/
void print(int **p, int row, int col)
{
 int i=0,j=0;
 for(i=0;i<row;i++)
 {
  for(j=0;j<col;j++)
  {
   printf("%d\t",p[i][j]);
  }
 }
 printf("\n");
}
/*数组指针(*)[]作为形参,可以接受数组指针(*p)[3]作为实参的参数,从而传递二维数组*/
void print(int (*p)[3], int row, int col)
{
 int i=0,j=0;
 for(i=0;i<row;i++)
 {
  for(j=0;j<3;j++)
  {
   printf("%d\t",p[i][j]);
  }
 }
 printf("\n");
}

/************************************************************************/
/*  以下是动态申请二维数组的几种方法     

int ** Ptr <==> int Ptr[ x ][ y ]; 行列不固定
int *Ptr[ 5 ] <==> int Ptr[ 5 ][ x ]; 行数固定
int ( *Ptr )[ 5 ] <==> int Ptr[ x ][ 5 ]; 列数固定
这里 x 和 y 是表示若干的意思。                            */
/************************************************************************/

/*方法一:二级指针,需要两次初始化,并且申请出来的二维数组只是逻辑上连续,物理上并不连续*/
void init1()
{
 int **p;
 int i=0,j=0;
 int row=4,col=3;
 p = new int*[row];//先初始化二级指针
 for(i=0;i<row;i++)//再初始化二级指针所指的指针数组的每个指针元素
 {
  //*(p+i) = new int[col];
  p[i] = new int[col];
 }
 
 //赋值
 for (i=0;i<row;i++)
 {
  for (j=0;j<col;j++)
  {
   p[i][j]=7;
  }
 }
 print(p,row,col);

//释放空间要注意顺序
 for (i=0;i<row;i++)
 {
  //delete[] *(p+i);
  delete[] p[i];
  printf("init1 释放p[%d]\t",i);
 }
 delete[] p;
 printf("\ninit1 二级指针**p被释放\n");
}
/*方法二:数组指针,这里可以一次性申请一片连续空间的二维数组*/
void init2()
{
 int i=0,j=0,row=4;
 const int col = 3;
 //int (*p)[col] = new int[row][col];//一步直接申请到位
 int (*p)[col] = (int(*)[col])new int[row*col];
 //赋值
 for (i=0;i<row;i++)
 {
  for (j=0;j<col;j++)
  {
   p[i][j]=8;
  }
 }
 print(p,row,col);
 delete[] p;
 printf("init2 数组指针(*p)[]被释放\n");
}
/*方法三:也是二级指针,语法上难理解一些,因为在直接操作地址,但是这个事一次性把二维数组所需空间申请完,而不是像方法一一样要多次申请。因此效率更高*/
void init3()
{
 int **p;
 int i=0;
 int row=4,col=3;
 p = (int **)new int[row+row*col];//这个空间包含了4个指针和12个数组元素(注意这里有一个bug,因为在32位系统所以指针位数和int位数一样长,如果在64位系统可能会出错)
 int *head = (int *)((int)p+row*sizeof(int *));//计算出二维数组的首地址
 for (i=0;i<row;i++)
 {
  p[i] = (int *)((int)head+i*col*sizeof(int));//给4个指针赋二维数组每一行的地址值
 }

for (i=0;i<row;i++)
 {
  for (int j=0;j<col;j++)
  {
   p[i][j] = 9;
  }
 }
 print(p,row,col);
 delete[] p;
 printf("init3 高效版二级指针**p被释放\n");
 
}
/*方法四:指针数组,行数是固定的*/
void init4()
{
 const int row=4;
    int col=3;
 int *p[row];
 int i=0,j=0;

for(i=0;i<row;i++)//再初始化指针所指的数组行地址
 {
  //*(p+i) = new int[col];
  p[i] = new int[col];
 }
 
 //赋值
 for (i=0;i<row;i++)
 {
  for (j=0;j<col;j++)
  {
   p[i][j]=6;
  }
 }
 print(p,row,col);

delete[] *p;//!!!注意指针数组的释放方式
 printf("init4 指针数组*p[]被释放\n");
}


int main()
{
 init1();
 init2();
 init3();
 init4();
 return 0;
}

------------------------------分割线------------------------------

C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码

读C++ Primer 之构造函数陷阱

读C++ Primer 之智能指针

读C++ Primer 之句柄类

将C语言梳理一下,分布在以下10个章节中:

Linux-C成长之路(一):Linux下C编程概要

Linux-C成长之路(二):基本数据类型

Linux-C成长之路(三):基本IO函数操作

Linux-C成长之路(四):运算符

Linux-C成长之路(五):控制流

Linux-C成长之路(六):函数要义

Linux-C成长之路(七):数组与指针

Linux-C成长之路(八):存储类,动态内存

Linux-C成长之路(九):复合数据类型

Linux-C成长之路(十):其他高级议题

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ddff835d80dc0b948414557fd900a068.html