7 C语言进阶之动态内存管理
7.1 动态内存函数
7.1.1 什么是动态数组
今天来学习四个内存动态函数,内存动态函数呢顾名思义就是在内存中开辟的一块空间,这块空间的大小是可以更改的。
7.1.2区别
- 举个例子,在我们之前学习的数组中,创建一个数组arr[]中的储存大小只要初始化了就是固定的了,例如arr[10],则数组arr的大小就是10*4(size_t * sizeof(arr[0]));假若我们在使用了arr[10],后还想扩大或者缩小,那么就只能手动调整,陷入内存分配不利的情况。于是就有了动态内存。
- 那么他们的根本区别呢还是在内存里。内存分为三个区:栈区、堆区和静态区(数据段)。栈区是用来存放局部变量和函数形参的;堆区是用来开辟动态内存的;静态区是存放全局变量和静态变量的。那么显而易见,动态内存的开辟都是在堆区进行,而我们今天讲的四个动态内存函数同样也是,下面这幅图可以更直观的理解。
那我们就来学习malloc、calloc、realloc、free这四个动态内存函数。
7.2 malloc函数
7.2.1 函数原型
void*malloc(size_t size)
在stdlib.h头文件中包含该函数,作用是在内存中动态的分配一块size大小的内存空间。malloc函数会返回一个指针,该指针指向分配的内存空间,如果出现错误,则返回NULL。
注意:在使用malloc函数分配的内存空间是在堆中,而不是在栈中。因此在使用完这块内存之后一定要将其释放掉,释放内存空间使用的是free函数(见4.free函数)。
7.2.2 函数使用与理解
int* p;
p = (int*)malloc(sizeof(int));
- 首先定义指针p用来保存分配内存的地址。在使用malloc函数分配内存空间时,需要指定具体的内存空间的大小(size),这时调用sizeof函数就可以指定类型的大小。malloc函数成功分配内存空间后会返回一个指针,因为分配的是一个int型空间,所以在返回指针时也应该是相对应的int型指针,这样就要进行强制类型转换。最后将函数返回的指针赋值给指针p就可以保存动态分配的整型空间地址了。
7.2.3 示例
//我们来看看如何使用malloc函数动态分配空间
#include<stdio.h>
#include<stdlib.h>
int main()
{
//开辟10个整型空间
//int arr[10];//栈区
//动态内存开辟的
int* p = (int*)malloc(10 * sizeof(int));//默认是void*
//使用这些空间的时候
if (p == NULL)
{
perror("main");
return 0;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", p[i]);
}
//回收空间
free(p);
p = NULL;//手动把p置为空指针
return 0;
}
那么运行程序,动态内存就已经开辟出来了,显示效果如图:
7.3 calloc函数
7.3.1 函数原型
void* calloc(size_t num,size_t size)
在stdlib.h头文件中包含该函数,其功能是在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址,如果出现错误,则返回NULL。
7.3.2 函数使用与理解
int* pa; //定义指针
pa = (int*)calloc(3,sizeof(int)); //分配内存数组
- 上述代码中的pa为一个整型指针,使用calloc函数分配内存数组,在参数中第一个参数表示分配数组中元素的个数,而第二个数组参数表示元素的类型。最后将返回的指针赋给pa指针变量,pa指向的就是该数组的首地址。
7.3.3 示例
#include<stdio.h>
#include<stdlib.h>
int main()
{
//int* p = (int*)malloc(40);
int* p = (int*)calloc(10, sizeof(int));
if (p == NULL)
return 1;
int i = 0;
//callocall自动为函数进行初始化成0
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
free(p);
p = NULL;
return 0;
}
那么运行程序,动态内存就已经开辟出来了,并且对每个元素都进行了初始化,显示效果如图:
7.4 realloc函数
7.4.1 函数原型
void* realloc(void* ptr,size_t size)
同样地,使用realloc函数要包含头文件stdlib.h,其功能是改变ptr指针指向的空间大小为size大小。设定的 size大小可以是任意的也就是说既可以比原来的数值大,也可以比原来的数值小。返回值是一个指向新地址的指针,如果出现错误,则返回NULL。
7.4.2 函数使用与理解
fdouble = (double*)malloc(sizeof(double));
iInt = realloc(fdouble,sizeof(int));
7.4.3 示例
- 其中fdouble是指向分配的实型空间,之后使用realloc函数改变fdouble指向的空间的大小,其大小设置为整型,然后将改变后的内存空间的地址返回赋值给iInt整型指针。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));
if (p == NULL)
{
perror("main");
return 1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = 5;
}
//需要p指向的空间更大,需要20个int的空间
//realloc调整空间
int* ptr = (int*)realloc(p, 20 * sizeof(int));
if (ptr != NULL)
{
p = ptr;
}
free(p);
p = NULL;
return 0;
}
- 因为函数改变了内存空间中数组的大小,因此可以在调试中进行观察。
7.5 free函数
7.5.1函数原型
void free(void* ptr)
free函数的功能是使用指针指向ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。
7.5.2 函数使用与理解
free(plnt);//释放
plnt = NULL;//将释放的指针置空
7.4.3 示例
free函数的示例在前面几个函数使用示例中已经展现出来了。free函数一定要与calloc和malloc函数同时使用。