Chinaunix首页 | 论坛 | 博客
  • 博客访问: 564681
  • 博文数量: 127
  • 博客积分: 1169
  • 博客等级: 少尉
  • 技术积分: 1298
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-16 14:29
个人简介

空白

文章分类

全部博文(127)

分类: C/C++

2012-02-29 00:17:24

一. 静态数组与动态数组
   静态数组比较常见,数组长度预先定义好,在整个程序中,一旦给定大小后就无法再改变长度,静态数组自己自动负责释放占用的内存。
   动态数组长度可以随程序的需要而重新指定大小。动态数组由内存分配函数(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)这四个函数头文件均包含在中。   
(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.     for (i = 0; i < x; i++)
  13.     {
  14.         pArr[i] = (int **)malloc(y * sizeof(int *));
  15.         for (j = 0; j < y; j++)
  16.         {
  17.            pArr[i][j] = (int *)malloc(z * sizeof(int));
  18.            for (k = 0; k < z; k++)
  19.            {
  20.               pArr[i][j][k] = i + j + k;
  21.            }
  22.         }
  23.     }
  24. }
内存释放函数:
  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:32
  3.     目的:多维数组构建和释放,这里以构建一个动态3维数组为例
  4. */

  5. #include <stdio.h>
  6. #include <malloc.h>

  7. void Malloc3DActiveArray(int *** pArr, int x, int y, int z);
  8. void Free3DActiveArray(int *** pArr, int x, int y);
  9. //void Display3DArray(int *** pArr, int x, int y, int z);


  10. int main(void)
  11. {
  12.     int x, y, z;
  13.     int *** array = NULL;

  14.     printf("输入一维长度: ");
  15.     scanf("%d",&x);
  16.     printf("输入二维长度: ");
  17.     scanf("%d",&y);
  18.     printf("输入三维长度: ");
  19.     scanf("%d",&z);

  20.     Malloc3DActiveArray(array, x, y, z);
  21.     Free3DActiveArray(array, x, y);
  22.     array = NULL;

  23.     return 0;
  24. }

  25. void Malloc3DActiveArray(int *** pArr, int x, int y, int z)
  26. {
  27.     int i, j, k;
  28.     pArr = (int ***)malloc(x * sizeof(int **));

  29.     for (i = 0; i < x; i++)
  30.     {
  31.         pArr[i] = (int **)malloc(y * sizeof(int *));
  32.         for (j = 0; j < y; j++)
  33.         {
  34.             pArr[i][j] = (int *)malloc(z * sizeof(int));
  35.             for (k = 0; k < z; k++)
  36.             {
  37.                 pArr[i][j][k] = i + j + k + 1;
  38.                 printf("%d ", pArr[i][j][k]);
  39.             }
  40.             printf("\n");
  41.         }
  42.         printf("\n");
  43.     }
  44. }

  45. void Free3DActiveArray(int *** pArr, int x, int y)
  46. {
  47.     int i, j;
  48.     for (i = 0; i < x; i++)
  49.     {
  50.         for (j = 0; j < y; j++)
  51.         {
  52.             free(pArr[i][j]);
  53.             pArr[i][j] = 0;
  54.         }

  55.         free(pArr[i]);
  56.         pArr[i] = 0;
  57.     }
  58.     free(pArr);
  59. }
  1. /*
  2.     2012年2月29日 12:32:02
  3.     功能:动态构建4维数组,学习动态构建多维数组,并释放多维数组
  4. */

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

  7. int main()
  8. {
  9.     int n1,n2,n3,n4;
  10.     int ****array;
  11.     int i,j,k,m;

  12.     puts("输入一维长度:");
  13.     scanf("%d",&n1);
  14.     puts("输入二维长度:");
  15.     scanf("%d",&n2);
  16.     puts("输入三维长度:");
  17.     scanf("%d",&n3);
  18.     puts("输入四维长度:");
  19.     scanf("%d",&n4);

  20.     array = (int ****)malloc(n1 * sizeof(int***));//第一维

  21.     for (i = 0; i < n1; i++)
  22.     {
  23.         array[i] = (int***)malloc(n2 * sizeof(int**)); //第二维
  24.         for (j = 0; j < n2; j++)
  25.         {
  26.             array[i][j] = (int**)malloc(n3 * sizeof(int*)); //第三维
  27.             for (k = 0; k < n3; k++)
  28.             {
  29.                 array[i][j][k] = (int *)malloc(n4 * sizeof(int));//第四维
  30.                 for (m = 0; m < n4; m++)
  31.                 {
  32.                     array[i][j][k][m] = i + j + k + m + 1;
  33.                     printf("%d\t", array[i][j][k][m]);
  34.                 }
  35.                 printf("\n");
  36.             }
  37.             printf("\n");
  38.         }
  39.         printf("\n");
  40.     }

  41.     for (i = 0; i < n1; i++)
  42.     {
  43.         for (j = 0; j < n2; j++)
  44.         {
  45.             for (k = 0; k < n3; k++)
  46.             {
  47.                 free(array[i][j][k]);//释放第四维指针
  48.                 array[i][j][k] = 0;
  49.             }

  50.             free(array[i][j]);//释放第三维指针
  51.             array[i][j] = 0;
  52.         }

  53.         free(array[i]);//释放第二维指针
  54.         array[i] = 0;
  55.     }

  56.     free(array);//释放第一维指针
  57.     array = NULL;

  58.     return 0;
  59. }

  60. /*
  61.     在vc++6.0中输出结果为:
  62.     -----------------------------------
  63.     输入一维长度:
  64.     1
  65.     输入二维长度:
  66.     2
  67.     输入三维长度:
  68.     3
  69.     输入四维长度:
  70.     4
  71.     1 2 3 4
  72.     2 3 4 5
  73.     3 4 5 6

  74.     2 3 4 5
  75.     3 4 5 6
  76.     4 5 6 7
  77.     Press any key to continue
  78. */
阅读(13009) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

generateRootCmd2017-05-20 18:38:39

void MallocAndFree3DActiveArray(int ***pArr,int x,int y,int z)
{
    int i,j,k;
    
    pArr = (int ***)malloc(x*sizeof(int **));
    
    for(i = 0;i < x;i++)
    {
        pArr[i] = (int **)malloc(y*sizeof(int *));
        for(j = 0;j < 

generateRootCmd2017-05-20 18:26:21

博主你好,如楼上所说,Free3DActiveArray中的free(pArr[i][j]);有段错误

foodtooth2013-08-02 19:52:52

博主你好。
你的
“2012年2月29日 12:00:32
  目的:多维数组构建和释放,这里以构建一个动态3维数组为例”
程序,似乎有segmentation fault错误。好像是因为在main里定义的指针数组在还没有地址的时候就被传到了Creat函数里。
请问是这样的吗?