C语言—动态内存管理—malloc、calloc、realloc

目录

1、前言

2、为什么要用到动态内存分配

3、动态内存函数的介绍

3.1 malloc和free

3.1.1 malloc

3.1.2 free

3.2 calloc

3.3 realloc

 结语


1、前言

首先我们要清楚,为什么C语言中给我们这样几个动态内存管理函数呢?定义一个确定空间的大小的数组不是更方便吗?带着这些问题,我们揭开今天的blog。

2、为什么要用到动态内存分配

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。

为了方便管理内存的空间大小,这时候就只能试试动态存开辟了!

3、动态内存函数的介绍

3.1 malloc和free

3.1.1 malloc

C语言提供了一个动态内存开辟的函数:

malloc一般按如下方式来使用:

int main()
{

	//申请空间
	int* ptr = (int*)malloc(40);
	if (ptr == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(ptr + i) = i;
	}
}

这个代码其实是存在问题的,因为没有用free来释放掉内存空间,容易发生内存泄漏的问题,因为free相关内容在下面有讲解,这里意在指明malloc的用法。

使用malloc开辟空间,需要注意以下几点:

  • malloc中size参数单位是字节,上面的代码的意思是开辟40个字节的空间。
  • malloc返回类型为void* 类型,如果想用int*的指针来接受,需要强制类型转换。
  • 如果malloc成功开辟空间,那就返回这个空间的起始地址
  • 如果开辟失败,就返回NULL空指针。所以在使用malloc之前一定要用if进行检查。
  • perror会返回内存出错的类型,并打印出来,加上malloc这个标题,方便我们定位到错误点的位置。

3.1.2 free

在malloc中已经说过,因为动态内存函数开辟的空间,如果程序一直运行,并且没有free释放空间,那么这段空间就会一直存在,不会被内存回收,这时候就会发生内存泄漏的问题,解决这一问题的最好方式就是在这段空间使用完成之后,加上free释放掉这段空间,即这段空间还能被其他的函数继续开辟,这就是free函数存在的意义。

代码更改为如下的形式:

int main()
{

	//申请空间
	int* ptr = (int*)malloc(40);
	if (ptr == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(ptr + i) = i;
	}
	//释放空间
	free(ptr);
	ptr = NULL;
	return 0;
}

free函数的使用,需要注意以下几点:

  • free函数释放完空间之后,一般与将ptr指针赋为空指针一起使用,这是因为:ree释放这段空间之后,这段空间就不属于我们了,但是ptr存放的还是首元素的地址,但是空间不属于我们了。就是野指针,就要把ptr = NULL; 
  • malloc申请空间之后,如果不主动释放,在程序结束的时候动态申请的内存由操作系统自动回收,如果程序不结束,我们又不主动释放,就回存在内存泄露的风险(可能被其他地方用了这个地方的内存)。
  • free释放的空间必须是动态内存函数(如:malloc、calloc、realloc)开辟的空间,其余的空间均不可以用free函数释放。

3.2 calloc

C语言还提供了一个函数叫calloc,calloc 函数也用来动态内存分配。原型如下:

  • 与函数malloc 的区别只在于calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
  • 函数的功能是为num 个大小为size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
  • calloc的两个参数: num是元素的个数,size是每个元素的长度(单位:字节,比如int就是4个字节),代码如下:
int main()
{
    int *p = (int*)calloc(10, sizeof(int));
    if(NULL == p)
    {
		perror("malloc");
		return 1;

    }
        free(p);
        p = NULL;
        return 0;
}

此段代码,在内存空间中开辟了10个类型为int型的数据空间

3.3 realloc

  • realloc函数的出现让动态内存管理更加灵活。
  • 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的分配内存,我们一定会对内存的大小做灵活的调整。那realloc 函数就可以做到对动态开辟内存大小的调整。函数原型如下:
void* realloc(void* ptr, size_t size)
  • ptr 是要调整的内存的元素首地址,size 调整之后新大小,注意:新大小指的是:如果原来有40个字节的空间,想扩容20个字节,那么一共是60个字节,size就是60。
  • realloc返回值为调整之后的内存起始位置。
  • realloc这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
  • realloc在调整内存空间的是存在2种情况:​​​​​​​
  1. 情况1:原有空间之后有足够大的空间。当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。​​​​​​​​​​​​​​
  2. 情况2:原有空间之后没有足够大的空间。当是情况2的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
  3. 如果内存中没有足够的空间给realloc函数扩容,那么就会返回NULL空指针。​​​​​​​​​​​​​​​​​​​​

C语言—动态内存管理—malloc、calloc、realloc_第1张图片

​​​​​​​

  • 代码如下:
#include 
int main()
{
    int *ptr = (int*)malloc(100);
    if(ptr != NULL)
    {
        //业务处理
    }
    //扩展容量
    int*p = NULL;
    p = realloc(ptr, 1000);
    if(p != NULL)
    {
        ptr = p;
    }
    //业务处理
    free(ptr);
    return 0;
}

 结语

动态内存函数开辟空间很方便,但是里面需要注意的细节也很多,比如:空间使用完之后,要用free函数释放空间;在使用动态内存函数之前要判断开辟空间是否成功(用if来判断是否为NULL空指针)等问题。

希望大家在看完我的blog之后能够有所收获!

你可能感兴趣的:(C语言,c语言,visualstudio)