malloc()函数实现内存动态分配

c语言中,变量在使用前必须被定义并且安排好存储空间,全局变量、静态局部变量的存储空间是在编译时确定,在程序开始执行前完成。函数参数、局部变量是在执行函数或者进入变量定义所在的复合语句时为它们分配存储空间,变量的大小也是静态确定的。

在实际编程的过程中,很多存储要求无法确定,例如常常很难为数组估计合适的大小,理想的做法是在运行时再确定数组的实际大小。C语言支持程序运行期间动态分配内存,这一功能只能通过指针来实现。关于指针的内存可以参考我的这篇博客:c语言指针详解

程序在运行期间,存放函数的参数值、局部变量值的内存区域有系统自动分配和释放,称为栈,而由程序员分配释放的内存区域称为堆。在分配堆上的内存时,由程序员跟踪所分配的内存,如果内存不再需要,注意要及时释放这些空间,以便于后面重用它们。关于栈和堆在动态内存分配的知识点很基础,而且经常出现在笔试中。

1.使用malloc()函数为数组分配内存

实现动态内存分配的最简单的标准库函数时malloc()。使用该函数,需要包含的头文件<stdlib.h>。malloc()函数的原型如下:

void *malloc(unsigned size);

函数的功能就是在内存分配的动态存储区分配长度为size个字节的内存空间。若申请成功,返回一个指向所分配内存空间的起始地址的指针;若申请分配内存空间不成功则返回NULL(值为0)。函数返回void*类型的值,void表示没有指定类型,void*类型的指针是通用指针,本质上只是内存地址,可以包含任何类型对象的地址.
关于通用指针的内容可以查看我的这篇博客通用指针

例如:

int *p = (int *)malloc(100);

将分配100个字节的内存块,并把这个内存块的首地址(也就是内存块第一个字节的位置)转换为int*类型,赋给指针变量p。因为malloc()函数的返回值为void类型的通用指针,所以需要进行类型转换,指明这块内存区里面的数据类型是int类型,假设int类型数据在机器上占4个字节,此时这个内存块上可以存放25个整数,如果不指明数据类型的话,在存读取数据的时候,无法知道读多少个字节将其转化为一个数据,所以进行类型转化的目的,就是明确告诉机器这块内存里面存放的是int类型的数据,每次读取4个字节作为一个整数。同样将数据写入这块内存区域时,也是每4个字节存入一个整数数据。

而上面的代码存在一些问题,因为不同的机器上int类型的长度是不同的,假设某个机器上int类型占5个字节,而程序员想的是占4个字节,则此时该内存块可以存储的int类型的数据小于预期,在进行具体的操作时,很容易导致数组访问越界的问题,进而导致系统崩溃等异常行为。所以在申请内存的时候,一定要使用sizeof运算符获取当前系统int类型所需的内存空间,也就是如下代码。

int *p =int *) malloc(n * sizeof(int));  //申请可以存放n个整数的内存块

在申请内存之后,最好检查下是否申请成功,如果p为NULL,则说明内存申请失败,最好执行适当的操作,例如显示“内存不足”等信息,然后终止程序。

因为数组和指针的关系密切,一旦p指向某内存块的首元素,就可以忽略p是指针之一事实,将其用作数组的名称,例如

int *p = (int *)malloc(n * sizeof(int));
for(i = 0; i < n; i++)
	p[i] = i;

2.释放动态分配的内存

在动态分配内存时,应该在不需要该内存时将内存释放,也就是malloc()和free配对出现。如果频繁的申请内存而没有及时释放不再需要的内存,可能会将内存耗尽。free()函数用来释放不需要的内存。原型如下:

void free(void *ptr);

free的形参时是void*类型,所以任何类型的指针都可以做实参传递给这个函数,但要求这个实参必须是先前由分配函数返回的指针。要释放动态分配的内存,而该内存的地址存储在指针p中,可以使用如下语句:free(p);
注意free后,p中的地址值并没有改变。

3. 其他动态内存分配函数

  • 使用calloc()函数动态分配内存
    原型为void *calloc(unsigned n,unsigned size),为n个元素的数组分配内存,每个元素的长度是size个字节。与malloc()函数的最大区别是,calloc()函数会通过把所有字节置0来初始化该内存空间。
  • 使用realloc()函数动态分配内存
    原型为void *realloc(void* ptr,unsigned size)该函数可以调整已经申请内存的大小。ptr指向原来通过malloc()、colloc()或realloc()获得的内存块,size是内存块的新尺寸。ptr也可为空指针,此时realloc()函数的作用等同于malloc()函数。

关于malloc函数更深入的内容可以参考这篇博客 https://blog.csdn.net/flowing_wind/article/details/81240910

猜你喜欢

转载自blog.csdn.net/qq_38048756/article/details/111699307