大家好!我是保护小周,本期为大家带来超详细的C语言——动态内存管理,论动态内存在C++/C中的重要性,学好动态内存约等于看穿了C语言~确定不来看看嘛~
目录
快来跟我一起学习吧!
一、为什么存在动态内存分配
当前我们知道的内存的使用方式:
(1)创建一个变量
创建一个变量就一定会开辟空间,例如:int sum=0; 如果sum变量在函数内部创建的,这个时候它是局部变量,又或者你定义的的sum是全局变量,无论是全局变量还是局部变量,作为整型的sum变量都会向内存申请4个字节的空间,无非就是局部变量是在内存的栈区上申请的,全局变量是在内存的静态区上申请的。
(2)创建一个数组
创建一个局部范围的数组,是在栈区上申请的,同样如果创建的是一个全局范围的数组,也是静态区上申请的。
我们来画个图换一种思维理解:
两种方式:一种是一次申请一个变量的空间,另一种是一次申请一片连续的空间。
上述两种开辟空间的方式有两个特点:
1.空间开辟的大小是固定的。
2.数组在申明的时候,必须指定数组的长度,所需内存在编译时分配。
那么是不是有了这两种常见的使用内存的方式就够了?
举个例子:我们采用一个结构体描述学生信息,学号、姓名、性别、年龄等信息;然后我们需要定义一个结构体类型变量,或者结构体类型数组来存储信息,如果我们采用一个数组存储一个班级的学生信息,我们当然可以根据一个班级里的人数来定义数组的大小,这时候如果班级有的同学转走了,我们把他的信息处理掉之后,表面上是删除了,实际上属于他原来的空间一直存在,是不是造成了一定程度上空间的浪费,又或者是增加了一些新的同学,数组的大小是固定的,满了之后我们又该如何处理,增加这些新同学的信息呢?有的人这样想,我们把数组的大小定义的大一些,一点点的空间浪费可以接受的,那么如果我采用这个结构体类型的数组存放全校同学的信息,这个误差就非常大了。
#include<stdio.h>
//学生学习成绩类型定义
struct grade
{
int Chinese;//语文
int math; //数学
int English;//英语
};
//学生信息类型定义
struct student //定义一个student的结构体类型
{
char number[12];//学号
char name[12]; //姓名
char sex[5]; //性别
int age; //年龄
char tele[12]; //电话
char addr[20]; //地址
struct grade report;//成绩单
};
int main()
{
//定义一个student类型的数组data;
struct student data[50];//data可以存放50个同学的信息
//如果实际录入信息为30,就造成空间上的浪费
//如果实际需录入信息60,那我们data的空间不够
return 0;
}
如果大家在结构体方面有什么不明白的可以观看博主的另一篇博客:结构体(初阶)
使用数组的方式有他的局限性,应该怎么办?动态内存分配,等空间满了之后自动的在堆区上开辟我们理想大小的空间,用来存储。如果我们删除某个同学的信息之后,可以执行释放掉用于存储被删除同学信息的空间,这样是不是非常方便?
二、动态内存函数介绍
动态内存函数的在头文件<stdlib.h>
2.1 malloc()和free()
C语言提供了一个动态内存开辟的函数:
void* malloc (size_t size);
这个函数可以向内存申请一块连续可用的空间,并返回指向这块从堆区上开辟的空间的指针。
(1)如果空间开辟成功,则返回一个指向开辟好空间起始位置的指针
(2)如果空间开辟失败,则返回一个值为NULL的指针,我们可以利用这一点来判断malloc()是否成功开辟空间
(3)返回值的类型是void *,所以malloc()函数不知道开辟空间的类型,类型需要我们自己来决定
这个时候我们就需要根据自己的需要进行强类型转换。
C语言提供了一个free()函数,专门是用来做动态内存的释放和回收的。
free()函数调用形式如下:
void free(void*ptr);
free()函数用来释放动态开辟的空间。
(1)如果参数 ptr 指向的空间不是动态开辟的,free()函数的行为是未定义的
(2)如果参数 ptr 是NULL指针,则函数什么事也不做
我们举一个简单的例子来看看怎么使用malloc()函数和free()函数;
#include<stdio.h>
#include<stdlib.h>
int main()
{
//定义一个指针
int* p=NULL;
//指针p指向malloc()函数返回的空间的起始位置
p=(int*)malloc(10*sizeof(int));//向内存的栈区申请10个整型的空间
if (p==NULL)//判断申请空间是否成功
{
//打印错误提示
perror("malloc");
return;//中止程序
}
else//正常使用空间
{
int i = 0;
for (i=0;i<10;i++)//给申请的空间赋值
{
*(p + i) = i;
}
//打印数据
for (i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
}
//当动态申请的空间不再使用
// 就应该还给操作系统
//释放空间
free(p); //如果我们不释放不