下面我们来看C语言中的动态内存管理,在之后的数据结构中会运用到C语言中的指针,结构体和动态内存管理,所以这部分还是比较重要的.下面进入正题.
为什么要有动态内存分配
但是上面的两种方式开辟的内存的大小都是固定的.数组也是,在数组开辟之前一定要确定好数组大小,并且数组开辟后空间大小不能被改变.
有时候我们需要的空间⼤⼩在程序运⾏的时候才能知道,那数组的编译时开辟空间的⽅式就不能满⾜了.C语⾔引⼊了动态内存开辟,让程序员⾃⼰可以申请和释放空间,这种方式这就比较灵活了.
下面我们就来看下动态内存分配的有关函数吧.
malloc和free
malloc
和之前复习一样我们先来看他的函数原型
void* malloc (size_t size);
free
C语⾔提供了另外⼀个函数free,专⻔是⽤来做动态内存的释放和回收的,函数原型见下
void free (void* ptr);
这两个函数都在头文件stdlib.h中.下面举个小例子
int main()
{
int* ptr = (int*)malloc(sizeof(int) * 10);
if (ptr == NULL)
{
perror("malloc");
return -1;
}
for (int i = 0; i < 10; i++)
{
*(ptr + i) = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", *(ptr + i));
}
printf("\n");
//一定不要忘记释放内存,否则会内存泄漏
free(ptr);
//释放后要及时置空
//free无法置空传入指针,因为free是传值调用
ptr = NULL;
return 0;
}
calloc和realloc
calloc
calloc也是C语言提供的用于动态内存的分配的函数.下面让我们看下他的函数原型吧
void* calloc (size_t num, size_t size);
1.函数的功能是为 num 个大小为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0.
(只能初始化为0,不可以指定初始化内容,不要与memset搞混了如果区分不开可以看下
C语言复习笔记--内存函数-CSDN博客)
2.与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0。
例子见下
int main()
{
int* ptr = (int*)calloc(10, sizeof(int));
if (ptr == NULL)
{
perror("malloc");
return -1;
}
//没有进行赋值直接打印
for (int i = 0; i < 10; i++)
{
printf("%d ", *(ptr + i));
}
printf("\n");
//一定不要忘记释放内存,否则会内存泄漏
free(ptr);
//释放后要及时置空
//free无法置空传入指针,因为free是传值调用
ptr = NULL;
return 0;
}
输出结果
realloc
函数原型见下
void* realloc (void* ptr, size_t size);
ptr 是要调整的内存地址
size 调整之后新大小
函数作用:
情况2时,函数会做找到新空间开辟,赋值原空间的值到新空间,释放原空间,然后返回新空间的地址这几件事情.
realloc使用例子
int main()
{
int* ptr = (int*)malloc(sizeof(int) * 10);
if (ptr == NULL)
{
perror("malloc");
return -1;
}
for (int i = 0; i < 10; i++)
{
*(ptr + i) = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", *(ptr + i));
}
printf("\n");
//空间不够了想扩容
int* tmp = (int*)realloc(ptr, sizeof(int) * 15);
//不能直接给tmp,因为扩容失败返回空指针,直接给的话连之前的空间都找不到了,会发生内存泄露
if (NULL == tmp)
{
perror("realloc");
return -1;
}
ptr = tmp;
for (int i = 10; i < 15; i++)
{
*(ptr + i) = i;
}
for (int i = 0; i < 15; i++)
{
printf("%d ", *(ptr + i));
}
printf("\n");
//一定不要忘记释放内存,否则会内存泄漏
free(ptr);
//释放后要及时置空
//free无法置空传入指针,因为free是传值调用
ptr = NULL;
return 0;
}
输出结果
常见的动态内存的错误
要对开辟出来的动态内存进行一下检查.
尽量不要让接收动态开辟内存函数返回的指针进行自加自减运算.
释放后记得将指针制空.
忘记释放不再使⽤的动态开辟的空间会造成内存泄漏。
切记:动态开辟的空间⼀定要释放,并且正确释放。
以上就是动态内存分配的基本知识,还有和这里相关的一个小语法柔性数组,想要了解一下可以看这篇博客C语言复习--柔性-CSDN博客.
我们下篇博客见.