对于我们学习一门计算机编程语言,“内存”是我们永远绕不开的一个词。对于初始C语言的小伙伴来说;我们只要知道内存被分为栈区,堆区,静态区即可。
1、栈区:主要是用来存放“局部变量”和“函数的形参”,在编译结束后编译器会自动释放栈区内存。
2、堆区:主要是用来开辟动态内存,再堆区的内存在函数中就需要程序员自己手动释放自己开辟的内存。
3、静态区:静态区又称为数据段,静态区主要用来存放“全局变量”和“静态变量”。静态区内存由编译器自行分配和释放。例如:
而我们今天的主题与堆区紧密相关。
所谓动态内存分配,就是程序员自己手动向系统的堆区申请所需空间的大小。对于申请的方式,就需要头文件#include<stdlib.h>中,malloc , calloc , realloc ,free这四个库函数了。
一、malloc函数和free函数
这两个函数是我们动态内存分配中最最最常用的两个函数。通俗来说,malloc是借用内存,而free就是归还内存。值得注意的是malloc函数的返回值为指针类型,该指针指向所借用内存空间的第一个字节的地址(malloc函数是开辟的内存空间是连续不断的)。free函数是释放malloc函数指针所指向的已分配的动态内存空间,同样值得注意的是free函数无返回值。
然而当我们在向系统借用内存空间后,为了确定我们是否借用成功,往往会需要一个的判断。在下面的代码段中,我将详细为大家介绍:
#include<stdio.h>
#include<stdlib.h>//动态内存分配所需头文件
#include<string.h>//str字符头文件
#include<errno.h>//打印错误所需的头文件
int main()
{
int*p = (int*)malloc(12);//向系统申请了3个整型类型的空间
if(p == NULL)
{
printf("%s\n",strerror(errno));//打印错误原因的方式用了一个if语句。
}
else
{
int i = 1;
for(i=1;i<4;i++)
{
*(p+i) = i;
}
for(i=1;i<4;i++)
{
printf("%d ",*(p+i));
}
}
free(p);//无返回值
p = NULL;//释放后指针并不会为空,因此我们应该给指针赋值为NULL
return 0;
}
二、calloc函数
calloc函数是与malloc函数非常类似的,它们的返回值都是指针类型,不同点在与描述的方式不同,calloc函数借用内存后会自动初始化所有内容为0,而malloc并不会自动初始化。
假如同样开辟10个int类型的内存空间如图:
对于初始化为0;我们只需简单的改一下上面的代码并看输出结果:
#include<stdio.h>
#include<stdlib.h>//动态内存分配所需头文件
#include<string.h>//str字符头文件
#include<errno.h>//打印错误所需的头文件
int main()
{
int*p = (int*)calloc(3,4);//向系统申请了3个整型类型的空间
if(p == NULL)
{
printf("%s\n",strerror(errno));//打印错误原因的方式用了一个if语句。
}
else
{
int i = 1;
for(i=1;i<4;i++)
{
printf("%d ",*(p+i));
}
}
free(p);//无返回值
p = NULL;//释放后指针并不会为空,因此我们应该给指针赋值为NULL
return 0;
}
这下关于初始化为0,我想大家都懂了吧!
三、realloc函数
realloc函数其原型为void*realloc(void*p,unsigned int size);如果已经通过malloc或calloc函数获得了动态空间,想改变其大小,这时可以用realloc函数重新分配。
上图中,使用realloc函数重新开辟动态内存空间,为了避免混淆,可以定义新的指针变量;上图realloc函数中将p所指向的动态空间的大小重新改为10个整型类型。realloc函数会自动释放上述用malloc或calloc函数开辟的动态内存空间;并重新开辟,因此在后面使用free函数释放时,我们之需要free(ptr),释放realloc所指向的动态内存空间即可。
到这里!我想大家对动态内存分配都更加了解吧!不懂私信我哦!