📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:C语言学习
🎯长路漫漫浩浩,万事皆有期待
1.动态内存
1.1 概述:
在c/c++语言中,所谓动态内存分配,就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。
1.2.动态内存分配的意义:
我们在之前的学习过程中,在使用各种变量与数组等等功能时,都需要从内存中开辟出一片空间用于存放我们的数据,而在之前我们掌握的内存开辟方式有:
int value = 20;
//在内存栈空间上开辟4个字节的空间
char arr[10] = {
0 };
//在栈空间上开辟10个字节的连续空间
但是我们最经常时使用的这两种内存空间的开辟方式有一些共同的特点:
1.空间开辟大小是固定的。
2.数组在申明的时候必须指定数组的长度,它所需要的内存将会在编译时分配。
换句话说,这两种内存开辟方式都是静态内存分配
。
但是我们在日常的代码编写和程序使用过程中,对于空间的需求往往不仅限于上述情况。更多的时候我们需要的空间大小只有在在程序运行的时候才能知道。如此,数组等在编译时开辟空间的方式无法满足我们的实际运行需求。于是就需要使用一种更好的内存分配方式进行处理:动态内存分配
2.常用的动态内存函数
2.1 malloc 和 free:
malloc 函数(memory allocate,即内存分配)的作用为向内存的堆区申请空间来存储数据,free 函数的作用为释放使用 malloc 函数向堆区申请的空间,并将空间归还给内存的堆区空间,通过配合使用这两个函数可以从堆区申请(释放)动态内存空间。
2.1.1 malloc 函数:
malloc 函数的使用格式为:
void* malloc (size_t size);
从它的使用格式中我们可以看出,该函数向堆区申请了一块连续的空间,同时返回的是这块空间的指针。
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个 NULL 指针,故我们在使用时一定要仔细检查 malloc 函数的返回值。
- 返回值的类型是 void* ,即 malloc 函数并不了解开辟空间的类型,至于空间的具体类型将在使用时由使用者自己决定。
- 如果参数 size 为 0,则 malloc 函数的行为是标准未定义的,将会取决于编译器。
2.1.2 free 函数:
我们可以看到,free 函数的使用格式为:
void free (void* ptr);
不同的是,与 malloc 函数恰好相反,free函数的作用为释放动态开辟的内存,同时没有返回值:
1.如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
2.如果参数 ptr 是NULL指针,则 free 函数将什么都不会做。
2.1.3 malloc 函数与 free 函数的使用:
关于两个函数的实际使用,我们直接来看下面这段 malloc 函数与 free 函数的使用实例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* ptr = NULL;
//初始化指针
ptr = (int*)malloc(40);
//使用malloc函数动态申请40字节空间
//同时因为指针ptr类型为int*,而 malloc 函数的返回类型为void*,故使用强制类型转换
int* p = ptr;
//在此定义指针p的原因是,在之后的使用中,指针p的指向会发生改变
//若不对初始指针指向进行保存,将无法释放改变前与改变后之间的空间
if (p == NULL)
//mallocc函数在动态空间开辟失败时返回空指针
//即若此处为空指针,说明动态内存空间申请失败
{
perror("malloc");
//打印malloc函数动态空间申请错误原因,并结束程序
return 1;
}
//没有结束说明指针不为空,动态空间申请成功
int i = 0;
for (i = 0; i < 10; i++)
{
*p = i;
//循环向动态内存空间中存入数据
p++;
//在此处的操作中,指针p的指向发生了改变
}
//使用完成后释放动态内存空间:
free(ptr);
//指针p指向发生改变,但指针ptr仍指向初始指针
ptr = NULL;
//动态内存空间归还后,重新将指针ptr置空
//动态内存空间已经归还,若不将指针ptr进行置空,指针ptr将变为野指针,指向将不可控,这在程序运行中非常危险
return 0;
}
对其中几个地方进行强调
:
- 在对指针进行操作前一定要保存指向初始位置的原始指针。
- 在对指向动态内存空间的指针进行使用前,一定要进行非空判断。
- 在动态内存空间使用完毕并释放后,一定要将指针进行置空操作。
- 当程序结束时若动态内存空间没有被释放,将会被操作系统自动回收。
- 但若程序不结束且申请的动态内存空间持续不归还,动态内存将不会被回收,就会导致内存泄漏问题。
2.2 calloc 函数:
calloc 函数的使用格式为:
void* calloc (size_t num, size_t size);
,calloc 函数的功能是为 num 个大小为 size 的元素开辟一块动态内存空间,并将空间内每个字节都初始化为 0。其使用方式与 malloc 函数无异:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* ptr = NULL;
ptr = (int*)calloc(10, sizeof(int));
//使用calloc函数动态申请10个int类型大小的空间
//同时因为指针ptr类型为int*,而calloc函数的返回类型为void*,故使用强制类型转换
int* p = ptr;
if (p ==