malloc、calloc、realloc、free内存动态函数使用

131 阅读4分钟

7 C语言进阶之动态内存管理

7.1 动态内存函数

7.1.1 什么是动态数组

今天来学习四个内存动态函数,内存动态函数呢顾名思义就是在内存中开辟的一块空间,这块空间的大小是可以更改的。

7.1.2区别

  • 举个例子,在我们之前学习的数组中,创建一个数组arr[]中的储存大小只要初始化了就是固定的了,例如arr[10],则数组arr的大小就是10*4(size_t * sizeof(arr[0]));假若我们在使用了arr[10],后还想扩大或者缩小,那么就只能手动调整,陷入内存分配不利的情况。于是就有了动态内存。
  • 那么他们的根本区别呢还是在内存里。内存分为三个区:栈区、堆区和静态区(数据段)。栈区是用来存放局部变量和函数形参的;堆区是用来开辟动态内存的;静态区是存放全局变量和静态变量的。那么显而易见,动态内存的开辟都是在堆区进行,而我们今天讲的四个动态内存函数同样也是,下面这幅图可以更直观的理解。

image.png

那我们就来学习malloc、calloc、realloc、free这四个动态内存函数。

7.2 malloc函数

7.2.1 函数原型

void*malloc(size_t size)

stdlib.h头文件中包含该函数,作用是在内存中动态的分配一块size大小的内存空间。malloc函数会返回一个指针,该指针指向分配的内存空间,如果出现错误,则返回NULL。

注意:在使用malloc函数分配的内存空间是在堆中,而不是在栈中。因此在使用完这块内存之后一定要将其释放掉,释放内存空间使用的是free函数(见4.free函数)。

7.2.2 函数使用与理解

int* p;
p = (int*)malloc(sizeof(int));
  • 首先定义指针p用来保存分配内存的地址。在使用malloc函数分配内存空间时,需要指定具体的内存空间的大小(size),这时调用sizeof函数就可以指定类型的大小。malloc函数成功分配内存空间后会返回一个指针,因为分配的是一个int型空间,所以在返回指针时也应该是相对应的int型指针,这样就要进行强制类型转换。最后将函数返回的指针赋值给指针p就可以保存动态分配的整型空间地址了。

7.2.3 示例

//我们来看看如何使用malloc函数动态分配空间
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//开辟10个整型空间
	//int arr[10];//栈区
	//动态内存开辟的
	int* p = (int*)malloc(10 * sizeof(int));//默认是void*
	//使用这些空间的时候
	if (p == NULL)
	{
		perror("main");
		return 0;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
		printf("%d ", p[i]);
	}
	//回收空间
	free(p);
	p = NULL;//手动把p置为空指针

	return 0;
}

那么运行程序,动态内存就已经开辟出来了,显示效果如图: image.png

7.3 calloc函数

7.3.1 函数原型

void* calloc(size_t num,size_t size)

在stdlib.h头文件中包含该函数,其功能是在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址,如果出现错误,则返回NULL。

7.3.2 函数使用与理解

int* pa; //定义指针
pa = (int*)calloc(3,sizeof(int)); //分配内存数组    
  • 上述代码中的pa为一个整型指针,使用calloc函数分配内存数组,在参数中第一个参数表示分配数组中元素的个数,而第二个数组参数表示元素的类型。最后将返回的指针赋给pa指针变量,pa指向的就是该数组的首地址。

7.3.3 示例

#include<stdio.h>
#include<stdlib.h>

int main()
{
	//int* p = (int*)malloc(40);
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
		return 1;
	int i = 0;
        //callocall自动为函数进行初始化成0
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

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

那么运行程序,动态内存就已经开辟出来了,并且对每个元素都进行了初始化,显示效果如图: image.png

7.4 realloc函数

7.4.1 函数原型

void* realloc(void* ptr,size_t size)

同样地,使用realloc函数要包含头文件stdlib.h,其功能是改变ptr指针指向的空间大小为size大小。设定的 size大小可以是任意的也就是说既可以比原来的数值大,也可以比原来的数值小。返回值是一个指向新地址的指针,如果出现错误,则返回NULL。

7.4.2 函数使用与理解

fdouble = (double*)malloc(sizeof(double));
iInt = realloc(fdouble,sizeof(int));

7.4.3 示例

  • 其中fdouble是指向分配的实型空间,之后使用realloc函数改变fdouble指向的空间的大小,其大小设置为整型,然后将改变后的内存空间的地址返回赋值给iInt整型指针。
#include<stdio.h>
#include<stdlib.h>

int main()
{
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		perror("main");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = 5;
	}
	//需要p指向的空间更大,需要20个int的空间
	//realloc调整空间
	int* ptr = (int*)realloc(p, 20 * sizeof(int));
	if (ptr != NULL)
	{
		p = ptr;
	}
	free(p);
	p = NULL;
	return 0;
}

  • 因为函数改变了内存空间中数组的大小,因此可以在调试中进行观察。

7.5 free函数

7.5.1函数原型

void free(void* ptr)

free函数的功能是使用指针指向ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。

7.5.2 函数使用与理解

free(plnt);//释放
plnt = NULL;//将释放的指针置空

7.4.3 示例

free函数的示例在前面几个函数使用示例中已经展现出来了。free函数一定要与calloc和malloc函数同时使用。