动态数组

在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些 内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。

遵循原则

  申请的时候从外层往里层,逐层申请;
  释放的时候从里层往外层,逐层释放。

构建所需指针

   对于构建一维动态数组,需要一维指针;
  对于二维,则需要一维,二维指针;
  三维需要一,二,三维指针;
  依此类推。

构建所需函数

  
函数原型返 回功能说明
void *malloc(unsigned int size);成功:返回所开辟
空间首地址 失败:返回空指针
向系统申请
size字节的
堆空间
void *calloc(unsigned int num, unsigned int size);成功:返回所开辟
空间首地址 失败:返回空指针
按类型申请
num个size字
节的堆空间
void free(void *p);无返回值释放p指向
的堆空间
void *realloc(void *p,unsigned int size);成功:返回新开辟
空间首地址 失败:返回空指针
将p指向的
堆空间变为
size

说明:

  (1)规定为void *类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使 用时根据各个域值数据再确定。可以用 强制转换的方法将其转换为别的类型。例如:double *pd=NULL; pd=(double *)calloc(10,sizeof(double)); 表示将向系统申请10个连续的 double类型的存储空间,并用指针pd指向这个连续的空间的首地址。并且用(double)对calloc( ) 的返回类型进行转换,以便把double类型数据的地址赋值给指针pd。
  (2)使用sizeof的目的是用来计算一种类型的占有的字节数,以便适合不同的 编译器
  (3)由于动态分配不一定成功,为此要附加一段异常处理程序,不致程序运行停止,使用户
  不知所措。通常采用这样的异常处理程序段:
  if(p==NULL) /* 或者if(!p)*/ { printf("动态申请内存失败!\n"); exit(1); //异常退出 }
  (4)这四个函数头文件均包含在<stdlib.h>中。
  (5)分配的堆空间是没有名字的 只能通过返回的指针找到它。
  (6)绝不能对非动态分配存储块使用free。也不能对同一块内存区同时用free释放两次。
  如:free(p);free(p);
  (7)调用 free() 时, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因为p是作为形参而传递给了函数。严格的讲, 被释放的指针值是无效的, 因为它已不再指向所申请的内存区。这时对它的任何使用便可能会可带来问题。
  malloc与calloc的区别
  对于用malloc分配的内存区间,如果原来没有被使用过,则其中的每一位可能都是0;反之, 如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说, 使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题,因此在使用它之前必须先进行初始化(可用memset函数对其初始化为0),但调用calloc()函数分配到的空间在分配时就已经被初始化为0了。 当你在calloc()函数和malloc()函数之间作选择时,你需考虑是否要初始化所分配的内存空间,从而来选择相应的函数。

具体构建方法

  以三维整型 数组array[n1][n2][n3]为例。
  先遵循从外层到里层,逐层申请的原则:
  最外层指针是array,它是个三维指针,所指向的是array[],其为二维指针。所以给array 申请内存应:
  array=(int***)calloc(n1,sizeof(int**)); 次层指针是array[],它是个二维指针,所指向的是array[][],其为一维指针。所以给array[] 申请内存应:
  for(i=0;i<n1;i++)
  {
  array[i]=(int**)calloc(n2,sizeof(int*));
  }
  最内层指针是array[][],它是个一维指针,所指向的是array[][][],其是个整型常量。所 以给array[][]申请内存应:
  for(i=0;i<n1;i++)
  {
  for(j=0;j<n2;j++)
  {
  array[i][j]=(int*)calloc(n3,sizeof(int));
  }
  }
  当然,你可以把它们整合在一起为:
  int i,j,k;
  int n1,n2,n3;
  int ***array;
  scanf("%d%d%d",&n1,&n2,&n3);
  array=(int***)calloc(n1,sizeof(int**));
  for(i=0;i<n1;i++)
  {
  array[i]=(int**)calloc(n2,sizeof(int*));
  for(j=0;j<n2;j++)
  {
  array[i][j]=(int*)calloc(n3,sizeof(int));
  for(k=0;k<n3;k++)
  {
  array[i][j][k]=i+j+k+1;
  }
  }
  }
  最后不要忘了释放这些内存,这要遵循释放的时候从里层往外层,逐层释放的原则。
  分析过程可参考上面的解答,这里不再赘述。只给出代码吧:
  for(i=0;i<n1;i++)
  {
  for(j=0;j<n2;j++)
  {
  free(array[i][j]);//释放第三维指针
  }
  }
  for(i=0;i<n1;i++)
  {
  free(array[i]);//释放第二维指针
  }
  free(array);//释放第一维指针
  其余维的如四维创建过程大同小异,这里不再赘述。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值