一. 静态数组与动态数组
静态数组比较常见,数组长度预先定义好,在整个程序中,一旦给定大小后就无法再改变长度,静态数组自己自动负责释放占用的内存。
动态数组长度可以随程序的需要而重新指定大小。动态数组由内存分配函数(malloc)从堆(heap)上分配存储空间,只有当程序执行了分配函数后,才为其分配内存,同时由程序员自己负责释放分配的内存(free)。
二. 为什么要使用动态数组?
在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,c语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
三. 动态数组与静态数组的比较
对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!
对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则严重会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。
四. 如何构建动态数组?
构建动态数组时,我们遵循下面的原则:申请的时候从外层往里层,逐层申请;
释放的时候从里层往外层,逐层释放;
五. 如何构建动态数组所需指针?
对于构建一维动态数组,需要一维指针;
对于二维,则需要一维,二维指针;
对于三维,需要一,二,三维指针;
依此类推。
六. 动态内存分配与释放函数
-
/*动态内存分配与释放函数*/
-
void *malloc(unsigned int size);
-
void *calloc(unsigned int num, unsigned int size);
-
void *realloc(void *p,unsigned int size);
- void free(void *p);
(1)
malloc()函数成功:返回所开辟空间首地址;失败:返回空指针;功能:向系统申请size字节堆的空间;
calloc()成功:返回所开辟空间首地址;失败:返回空指针;功能:按类型向系统申请num个size字节堆的空间;
realloc()成功:返回所开辟空间首地址;失败:返回空指针;功能:将p指向的空间变为个size字节堆的空间;
free()没有返回值,释放p指向的堆空间;
(2)
规定为void *类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使用时根据各个域值数据再确定。可以用强制转换的方法将其转换为别的类型。例如:
- double *pd = NULL;
- pd = (double *)calloc(10, sizeof(double));
(3)
使用sizeof的目的是用来计算一种类型的占有的字节数,以便适合不同的编译器。
(4)检查动态内存是否分配成功
由于动态分配不一定成功,为此要附加一段异常处理程序,不致程序运行停止,使用户不知所措。通常采用这样的异常处理程序段:
-
if (p == NULL) /* 或者if(!p)*/
-
{
-
printf("动态申请内存失败!\n");
-
exit(1); //异常退出
-
}
(6)分配的堆空间是没有名字的,只能通过返回的指针找到它。
(7)绝不能对非动态分配存储块使用free。也不能对同一块内存区同时用free释放两次,如:
-
free(p);
- free(p);
-
int *p = (int *)malloc(sizeof(int));
-
free(p); /*释放p指向内存*/
- p = 0; /*或者 p = NULL,释放p指向的内存后,将p指针赋值为0,避免p指针成为野指针*/
六.动态数组构建过程
以三维整型数组为例int array[x][y][z]
先遵循从外到里,逐层申请的原则:
最外层的指针就是数组名array,他是一个三维指针,指向的是array[],array[]是二维指针,所以给array申请内存空间需要一个三维指针int *** p;
-
/*给三维数组array[x][y][z]动态分配内存*/
- int *** p = (int ***)malloc(x * sizeof(int **));
- /*或者如下*/
-
array = (int ***)malloc(x * sizeof(int **))
- /*指针p指向的是array三维数组的第一维,有x个元素,所以要sizeof(x * (int **))*/
-
int i, j;
-
for (i = 0; i < x; i++)
-
{
-
array[i] = (int **)malloc(y
* sizeof(int *));
- }
-
int i, j;
-
for (i = 0; i < x; i++)
-
{
-
for (j = 0; j < y; j++)
-
{
-
array[i][j] = (int *)malloc(z * sizeof(int));
-
}
- }
-
/*动态构建三维数组内存分配函数*/
-
/*
-
* pArr: 指向三维数组首地址
-
* x: 三维数组第一维元素个数
-
* y: 三维数组第二维元素个数
-
* z: 三维数组第三维元素个数
- */
- void Create3DActiveArray(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 < y; j++)
-
{
-
pArr[i][j] = (int *)malloc(z * sizeof(int));
-
for (k = 0; k < z; k++)
-
{
-
pArr[i][j][k] = i + j + k;
-
}
-
}
- }
- }
-
void Free3DActiveArray(int ***pArr, int x, int y)
-
{
-
int i, j, k;
-
for (i = 0; i < x; i++)
-
{
-
for (j = 0; j < y; j++)
-
{
-
free(pArr[i][j]);
-
pArr[i][j] = 0;
-
}
-
free(pArr[i]);
-
pArr[i] = 0;
-
}
-
free(pArr);
-
- }
-
/*
-
2012年2月29日 12:00:32
-
目的:多维数组构建和释放,这里以构建一个动态3维数组为例
-
*/
-
-
#include <stdio.h>
-
#include <malloc.h>
-
-
void Malloc3DActiveArray(int *** pArr, int x, int y, int z);
-
void Free3DActiveArray(int *** pArr, int x, int y);
-
//void Display3DArray(int *** pArr, int x, int y, int z);
-
-
-
int main(void)
-
{
-
int x, y, z;
-
int *** array = NULL;
-
-
printf("输入一维长度: ");
-
scanf("%d",&x);
-
printf("输入二维长度: ");
-
scanf("%d",&y);
-
printf("输入三维长度: ");
-
scanf("%d",&z);
-
-
Malloc3DActiveArray(array, x, y, z);
-
Free3DActiveArray(array, x, y);
-
array = NULL;
-
-
return 0;
-
}
-
-
void Malloc3DActiveArray(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 < y; j++)
-
{
-
pArr[i][j] = (int *)malloc(z * sizeof(int));
-
for (k = 0; k < z; k++)
-
{
-
pArr[i][j][k] = i + j + k + 1;
-
printf("%d ", pArr[i][j][k]);
-
}
-
printf("\n");
-
}
-
printf("\n");
-
}
-
}
-
-
void Free3DActiveArray(int *** pArr, int x, int y)
-
{
-
int i, j;
-
for (i = 0; i < x; i++)
-
{
-
for (j = 0; j < y; j++)
-
{
-
free(pArr[i][j]);
-
pArr[i][j] = 0;
-
}
-
-
free(pArr[i]);
-
pArr[i] = 0;
-
}
-
free(pArr);
- }
-
/*
-
2012年2月29日 12:32:02
-
功能:动态构建4维数组,学习动态构建多维数组,并释放多维数组
-
*/
-
-
#include <stdlib.h>
-
#include <stdio.h>
-
-
int main()
-
{
-
int n1,n2,n3,n4;
-
int ****array;
-
int i,j,k,m;
-
-
puts("输入一维长度:");
-
scanf("%d",&n1);
-
puts("输入二维长度:");
-
scanf("%d",&n2);
-
puts("输入三维长度:");
-
scanf("%d",&n3);
-
puts("输入四维长度:");
-
scanf("%d",&n4);
-
-
array = (int ****)malloc(n1 * sizeof(int***));//第一维
-
-
for (i = 0; i < n1; i++)
-
{
-
array[i] = (int***)malloc(n2 * sizeof(int**)); //第二维
-
for (j = 0; j < n2; j++)
-
{
-
array[i][j] = (int**)malloc(n3 * sizeof(int*)); //第三维
-
for (k = 0; k < n3; k++)
-
{
-
array[i][j][k] = (int *)malloc(n4 * sizeof(int));//第四维
-
for (m = 0; m < n4; m++)
-
{
-
array[i][j][k][m] = i + j + k + m + 1;
-
printf("%d\t", array[i][j][k][m]);
-
}
-
printf("\n");
-
}
-
printf("\n");
-
}
-
printf("\n");
-
}
-
-
for (i = 0; i < n1; i++)
-
{
-
for (j = 0; j < n2; j++)
-
{
-
for (k = 0; k < n3; k++)
-
{
-
free(array[i][j][k]);//释放第四维指针
-
array[i][j][k] = 0;
-
}
-
-
free(array[i][j]);//释放第三维指针
-
array[i][j] = 0;
-
}
-
-
free(array[i]);//释放第二维指针
-
array[i] = 0;
-
}
-
-
free(array);//释放第一维指针
-
array = NULL;
-
-
return 0;
-
}
-
-
/*
-
在vc++6.0中输出结果为:
-
-----------------------------------
-
输入一维长度:
-
1
-
输入二维长度:
-
2
-
输入三维长度:
-
3
-
输入四维长度:
-
4
-
1 2 3 4
-
2 3 4 5
-
3 4 5 6
-
-
2 3 4 5
-
3 4 5 6
-
4 5 6 7
-
Press any key to continue
- */
写代码的时候会碰到多维数组的内存分配和释放问题,在分配和释放过程中很容易出现错误。下面贴上一些示例代码,以供参考。
二维数组(m*n)分配空间
如果要给二维数组(m*n)分配空间,代码可以写成下面:
char **a, i; // 先分配m个指针单元,注意是指针单元 // 所以每个单元的大小是sizeof(char *) a = (char **) malloc(m * sizeof(char * )); // 再分配n个字符单元, // 上面的m个指针单元指向这n个字符单元首地址 for(i = 0; i < m; i++) a[i] = (char * )malloc(n * sizeof(char )); |
(注意红色部分)
释放应该是:
int i; for(i=0;i<m;i++) free((void *)a[i]); free((void *)a); |
(
C中如何为第二维长度固定的二维数组分配内存
在所写的代码中,有时需要为一个二维数组分配内存,该二维数组的第一维长度不定,而 第二维是固定(类似arr[n][3]的数组)。我们可以想到的是用双指针代替数组,当然可以;也可以直接对n赋值后,直接定义arr[n][3] (C99标准支持),但这里要说的是另一种方法。
这里以将点云数据读入二维数组为例,由于点云点数n不定,可以确定的是,点是三维点,可以用以下方式定义并分配内存:
double (*arr)[3] = malloc (n*3*sizeof(double));
但在VC编译环境下,将会报错——无法从“void *”转换为“double (*)[3]” ,此时应该在malloc函数之前进行类型转换,应该如何转换呢?怎样转换才能成double (*)[3]类型呢,可以进行如下转换:
double (*arr)[3] = (double ((*)[3]))malloc (n*3*sizeof(double));
搞定!:)。
三维数组(m*n*p)分配空间
如果为三维数组(m*n*p)分配空间呢,应该是:
char ***a, i, j; a = (char ***) malloc(m * sizeof(char ** )); for(i = 0; i < m; ++i) a[i] = (char **) malloc(n * sizeof(char * )); for(i = 0; i < m; ++i) for(j = 0; j < n; ++j) a[i][j] = (char * )malloc(p * sizeof(char )); |
释放代码为逆过程,具体代码为:
int i,j,; for(i = 0; i < m; ++i) for(j = 0; j < n; ++j) free((void *)a[i][j]); for(i = 0; i < m; ++i) free((void *)a[i]); free((void *)a); |
三维以上的多维数组的分配和释放,原理与上面的一样。
(转)