动态内存分配(malloc,realloc,calloc,free)的基本理解和区别

一.为什么要使用动态内存分配???

     以一个数组为例:在定义一个数组时给定了其内存空间,只要给定足够大的空间,就可以放入你所需的数据元素。但当内存空间小于所需放入的元素个数时,我们就需要给这个内存空间去增容,以此来满足你的需求。

      上述定义数组时设置足够大的内存空间看似简单,但却有以下缺点:

            1.如果内存空间很大,数据却很少就会使内存空间浪费。

            2.如果内存空间不足就会出现溢出的现象。

二.malloc

  1.   函数原型:

//头文件
#include<malloc.h>

//函数原型
void *malloc(sizt_t size);

malloc的参数就是需要所分配的字节数。

2. malloc在C语言中不是关键字而是C函数库中提供的函数。如果需要进行内存分配时在调用malloc时就是在内存池中提取一块内存空间(在堆上申请一块空间),但是这块空间是连续的空间。,并向该程序返回一个这块内存的指针。

注意:在申请完空间后需要自己去初始化这块空间,如果懒得动手那就可以用realloc(下面会介绍)

3.malloc进行内存分配的特点:

    (1.)所申请的空间是连续的

    (2.)在有的编译器下申请的空间略大于你请求申请的内存空间

    (3.)malloc所返回的内存起始位置将始终能够满足对边界对齐

4.malloc是如何知道你所申请的内存空间是什么类型?

     这是因为在使用malloc进行内存分配时会返回void*类型的指针,但是这个指针可以转化为任意类型的指针。(但是有些老式的编译器需要你去强转你所需要的类型)

 
 
#include<Windows.h>
#include<stdio.h>
#include<malloc.h>

int main()
{
	int* p = NULL;
	printf("%x\n", p);
	p = (int*)malloc(sizeof(int)* 25);
	if (NULL == p)
	{

		printf("申请失败!!!");
		return 0;

	}
	printf("%x\n", p);
	system("pause");
	return 0;
}


注意:由上边代码可以看到当用malloc动态分配空间后一定要进行对申请的空间进行判断是否申请失败,这点很重要。

二.calloc

    函数原型:

//有文件
#include<stdlib.h>

//源文件
void* calloc(size_t num_elements,size_t element_size);

calloc和calloc的动态分配内存是有相同之处,他们的主要区别在于:

(1.)在函数原型中calloc多了一个参数(他的参数是由所需元素的个数和每个元素的字节数组成)

(2.)最大区别:calloc在调用完后返回指向内存的指针之前把他初始化为0

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

int main()
{
	int* p = NULL;
	int* p1 = NULL;

	p = (int*)malloc(sizeof(int)* 5);
	if (NULL == p)
	{

		printf("申请失败!!!");
		return 0;

	}
  
	printf("malloc:\n");

	for (int i = 0; i < 5; i++)
	{
		printf(" %d-->", *p);
		*p++;

	}
	printf("\n");

	p1 = (int*)calloc(5, sizeof(int));
	if (NULL == p1)
	{

		printf("申请失败!!!");
		return 0;

	}

	printf("calloc:\n");
	for (int j = 0; j < 5; j++)
	{

		printf(" %d-->",*p1);
		*p1++;

	}
	
	system("pause");
	return 0;
}

注意:在调用完calloc后也要进行判断是否申请成功

三.realloc

  函数原型:

//头文件
#include<stdlib.h>

//原型
void realloc(void *ptr, size_t new_size);

ptr是指向原来地址的指针。

这个函数用于修改一个原先已经分配内存块的大小。

使用:

1.可以使一块内存扩大或缩小(原来的内存块可以扩大缩小)

  (1.)如果是扩大一个内存块,则将原来的内存块保留在他的后边新增一块内存块(但是新增的内存块并未初始化)

  (2.)如果是缩小一块内存块,则将该内存块的后半部分直接拿掉,剩余部分内存块及其内容保留。

2.原来的内存块无法扩大缩小

   如果是着这种情况,realloc会重新开辟一个新的内存空间,并把原来的内存空间的内容拷贝到新的内存空间里。

注意:再调用完realloc后就不能使用指向就内存的指针,而是用返回的新的指针。


值得一提的是:如果realloc中的第一个参数如果为空则和malloc一样。

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

int main()
{
	const int size = 2000;
	int *p = (int *)malloc(20 * sizeof(int));
	int *p1 = (int *)realloc(p, size*sizeof(int));
	
	printf("%x\n", p);
	printf("%x\n", p1);
	system("pause");
	return 0;
}





四.free(释放空间)

函数原型:

free(void* pointer);

free的参数必须要不时空,要不然就必须是malloc,calloc,realloc中返回值。

注意:在使用malloc,calloc,realloc进行内存分配后一定要进行释放空间。

五.内存空间


以上的操作都是在堆上进行

猜你喜欢

转载自blog.csdn.net/alidada_blog/article/details/80607267