动态指针数组申请和释放内存
- 格式:docx
- 大小:28.76 KB
- 文档页数:8
c语言中内存的动态分配与释放(多维动态数组构建) (2012-02-29 00:17) 标签: c语言内存动态分类:C/C++一. 静态数组与动态数组静态数组比较常见,数组长度预先定义好,在整个程序中,一旦给定大小后就无法再改变长度,静态数组自己自动负责释放占用的内存。
动态数组长度可以随程序的需要而重新指定大小。
动态数组由内存分配函数(malloc)从堆(heap)上分配存储空间,只有当程序执行了分配函数后,才为其分配内存,同时由程序员自己负责释放分配的内存(free)。
二. 为什么要使用动态数组?在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。
对于这种问题,用静态数组的办法很难解决。
为了解决上述问题,c语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
三. 动态数组与静态数组的比较对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则严重会引起内存泄露。
但其使用非常灵活,能根据程序需要动态分配大小。
四. 如何构建动态数组?构建动态数组时,我们遵循下面的原则:申请的时候从外层往里层,逐层申请;释放的时候从里层往外层,逐层释放;五. 构建动态数组所需指针对于构建一维动态数组,需要一维指针;对于二维,则需要一维,二维指针;对于三维,需要一,二,三维指针;依此类推。
六. 动态内存分配与释放函数1./*动态内存分配与释放函数*/2.void *malloc(unsigned int size);3.void *calloc(unsigned int num, unsigned int size);4.void *realloc(void *p,unsigned int size);5.void free(void *p);说明:(1)malloc()函数成功:返回所开辟空间首地址;失败:返回空指针;功能:向系统申请size字节堆的空间;calloc()成功:返回所开辟空间首地址;失败:返回空指针;功能:按类型向系统申请num个size 字节堆的空间;realloc()成功:返回所开辟空间首地址;失败:返回空指针;功能:将p指向的空间变为个size 字节堆的空间;free()没有返回值,释放p指向的堆空间;(2)规定为void *类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。
可以用强制转换的方法将其转换为别的类型。
例如:1.double *pd = NULL;2.pd = (double *)calloc(10, sizeof(double));表示将向系统申请10个连续的double类型的存储空间,并用指针pd指向这个连续的空间的首地址。
并且用(double)对calloc()的返回类型进行转换,以便把double类型数据的地址赋值给指针pd。
(3)使用sizeof的目的是用来计算一种类型的占有的字节数,以便适合不同的编译器。
(4)检查动态内存是否分配成功由于动态分配不一定成功,为此要附加一段异常处理程序,不致程序运行停止,使用户不知所措。
通常采用这样的异常处理程序段:1.if(p ==NULL)/*或者if(!p)*/2.{3.printf("动态申请内存失败!\n");4.exit(1);//异常退出5.}(5)这四个函数头文件均包含在<stdlib.h>中。
(6)分配的堆空间是没有名字的,只能通过返回的指针找到它。
(7)绝不能对非动态分配存储块使用free。
也不能对同一块内存区同时用free释放两次,如:1.free(p);2.free(p);(8)调用 free()时, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因为p 是作为形参而传递给了函数。
严格的讲, 被释放的指针值是无效的, 因为它已不再指向所申请的内存区。
这时对它的任何使用便可能会可带来问题。
所以在释放一个指针指向的内存后,将该指针赋值为0,避免该指针成为野指针:1.int*p =(int*)malloc(sizeof(int));2.free(p);/*释放p指向内存*/3.p = 0;/*或者 p =NULL,释放p指向的内存后,将p指针赋值为0,避免p指针成为野指针*/(9)malloc与calloc的区别,对于用malloc分配的内存区间,如果原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。
也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题,因此在使用它之前必须先进行初始化(可用memset函数对其初始化为0),但调用calloc()函数分配到的空间在分配时就已经被初始化为0了。
当你在calloc()函数和malloc()函数之间作选择时,你需考虑是否要初始化所分配的内存空间,从而来选择相应的函数。
六.动态数组构建过程以三维整型数组为例int array[x][y][z]先遵循从外到里,逐层申请的原则:最外层的指针就是数组名array,他是一个三维指针,指向的是array[],array[]是二维指针,所以给array申请内存空间需要一个三维指针int *** p;1./*给三维数组array[x][y][z]动态分配内存*/2.int*** p =(int***)malloc(x * sizeof(int**));3./*或者如下*/4.array = (int ***)malloc(x * sizeof(int **))5./*指针p指向的是array三维数组的第一维,有x个元素,所以要sizeof(x *(int**))*/次层指针是array[],它是一个二维指针,指向的是array[][],array[][]是一维指针:1.int i, j;2.for(i = 0; i < x; i++)3.{4.array[i]=(int**)malloc(y * sizeof(int*));5.}最内层指针是array[][],它是个一维指针,所指向的是array[][][],其是个整型常量。
所以给array[][]申请内存应:1.int i, j;2.for(i = 0; i < x; i++)3.{4.for(j = 0; j < y; j++)5.{6.array[i][j]=(int*)malloc(z * sizeof(int));7.}8.}综合以上三步:1./*动态构建三维数组内存分配函数*/2./*3.* pArr:指向三维数组首地址4.* x:三维数组第一维元素个数5.* y:三维数组第二维元素个数6.* z:三维数组第三维元素个数7.*/8.void Create3DActiveArray(int***pArr,int x,int y,int z)9.{10.int i, j, k;11.pArr =(int***)malloc(x * sizeof(int**));12.13.for(i = 0; i < x; i++)14.{15.pArr[i]=(int**)malloc(y * sizeof(int*));16.for(j = 0; j < y; j++)17.{18.pArr[i][j]=(int*)malloc(z * sizeof(int));19.for(k = 0; k < z; k++)20.{21.pArr[i][j][k]= i + j + k;22.}23.}24.}25.}内存释放函数:1.void Free3DActiveArray(int***pArr,int x,int y)2.{3.int i, j, k;4.for(i = 0; i < x; i++)5.{6.for(j = 0; j < y; j++)7.{8.free(pArr[i][j]);9.pArr[i][j]= 0;10.}11.free(pArr[i]);12.pArr[i]= 0;13.}14.free(pArr);15.16.}1./*2.2012年2月29日 12:00:323.目的:多维数组构建和释放,这里以构建一个动态3维数组为例4.*/5.6.#include <stdio.h>7.#include <malloc.h>8.9.void Malloc3DActiveArray(int*** pArr,int x,int y,int z);10.void Free3DActiveArray(int*** pArr,int x,int y);11.//void Display3DArray(int*** pArr,int x,int y,int z);12.13.14.int main(void)15.{16.int x, y, z;17.int***array=NULL;18.19.printf("输入一维长度: ");20.scanf("%d",&x);21.printf("输入二维长度: ");22.scanf("%d",&y);23.printf("输入三维长度: ");24.scanf("%d",&z);25.26.Malloc3DActiveArray(array, x, y, z);27.Free3DActiveArray(array, x, y);28.array=NULL;29.30.return 0;31.}32.33.void Malloc3DActiveArray(int*** pArr,int x,int y,int z)34.{35.int i, j, k;36.pArr =(int***)malloc(x * sizeof(int**));37.38.for(i = 0; i < x; i++)39.{40.pArr[i]=(int**)malloc(y * sizeof(int*));41.for(j = 0; j < y; j++)42.{43.pArr[i][j]=(int*)malloc(z * sizeof(int));44.for(k = 0; k < z; k++)45.{46.pArr[i][j][k]= i + j + k + 1;47.printf("%d ", pArr[i][j][k]);48.}49.printf("\n");50.}51.printf("\n");52.}53.}54.55.void Free3DActiveArray(int*** pArr,int x,int y)56.{57.int i, j;58.for(i = 0; i < x; i++)59.{60.for(j = 0; j < y; j++)61.{62.free(pArr[i][j]);63.pArr[i][j]= 0;64.}65.66.free(pArr[i]);67.pArr[i]= 0;68.}69.free(pArr);70.}1./*2.2012年2月29日 12:32:023.功能:动态构建4维数组,学习动态构建多维数组,并释放多维数组4.*/5.6.#include <stdlib.h>7.#include <stdio.h>8.9.int main()10.{11.int n1,n2,n3,n4;12.int****array;13.int i,j,k,m;14.15.puts("输入一维长度:");16.scanf("%d",&n1);17.puts("输入二维长度:");18.scanf("%d",&n2);19.puts("输入三维长度:");20.scanf("%d",&n3);21.puts("输入四维长度:");22.scanf("%d",&n4);23.24.array=(int****)malloc(n1 * sizeof(int***));//第一维25.26.for(i = 0; i < n1; i++)27.{28.array[i]=(int***)malloc(n2 * sizeof(int**));//第二维29.for(j = 0; j < n2; j++)30.{31.array[i][j]=(int**)malloc(n3 * sizeof(int*));//第三维32.for(k = 0; k < n3; k++)33.{34.array[i][j][k]=(int*)malloc(n4 * sizeof(int));//第四维35.for(m = 0; m < n4; m++)36.{37.array[i][j][k][m]= i + j + k + m + 1;38.printf("%d\t",array[i][j][k][m]);39.}40.printf("\n");41.}42.printf("\n");43.}44.printf("\n");45.}46.47.for(i = 0; i < n1; i++)48.{49.for(j = 0; j < n2; j++)50.{51.for(k = 0; k < n3; k++)52.{53.free(array[i][j][k]);//释放第四维指针54.array[i][j][k]= 0;55.}56.57.free(array[i][j]);//释放第三维指针58.array[i][j]= 0;59.}60.61.free(array[i]);//释放第二维指针62.array[i]= 0;63.}64.65.free(array);//释放第一维指针66.array= NULL;67.68.return 0;69.}70.71./*72.在vc++6.0中输出结果为:73.-----------------------------------74.输入一维长度:75.176.输入二维长度:77.278.输入三维长度:79.380.输入四维长度:81.482.1 2 3 483.2 3 4 584.3 4 5 685.86.2 3 4 587.3 4 5 688.4 5 6 789.Press any key to continue。