【c语言】【visual studio】动态内存管理,malloc,calloc,realloc详解。

引言:随着大一期末的到来,想必许多学生都学到内存的动态管理这一部分了,看望这篇博客后,希望能解除你心中对这一章节的疑惑。

(・∀・(・∀・(・∀・*)

fcd86daf76774b47ba0f81a14548685a.png

1.malloc详解

malloc的头文件是#include <sdtlib.h>,malloc - C++ Reference (cplusplus.com)

我们可以点进看看的malloc的详细内容

3cd425feee5846778cd6204de797177d.png

可以看到malloc返回值是void*类型,也就是说明在使用时我们还需要根据需要开辟空间的类型,强制类型转换成自己所要的类型。例如我们要开辟40个字节的空间,代码如下。

#include <stdlib.h>
int main()
{
	int* pa =(int *) malloc(10 * sizeof(int));
	return 0;
}

用数组的来写,如下

同样也可以实现空间的开辟,这里我们就来谈谈相同点与不同点。

#include <stdio.h>
int main()
{
	int pa[10];
	return 0;
}

相同点:

  1. 向内存申请一块空间
  2. 在程序结束时释放

不同点:

  1. 申请的内存位置不同,malloc在堆区,数组在栈区。
  2. 头文件不同,malloc头文件是<stdlib.h>,数组头文件是<stdio.h>
  3. 空间动态性,malloc所申请的空间是可变的,动态的可以通过使用realloc(下面会再讲解realloc的用法)来改变大小,数组所申请的空间是不可变的,定义完后就固定了。
  4. 数组定义时可以初始化空间内容,malloc申请空间时不能初始化内容,且其空间里的内容是随机值。
  5. malloc申请空间可能失败,数组不会。

如何理解这些不同点以及如何配套使用malloc我们看下面这一段代码

#include <stdlib.h>
int main()
{
	int* pa =(int *)malloc(10 * sizeof(int));
	if (pa == NULL)
	{
		perror("malloc:");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(pa+i) = i;
		printf("%d ", *(pa+i));
	}
	free(pa);
	pa = NULL;
	return 0;
}

我们可以看到,用malloc申请完空间后,我们接着写了一段代码判断pa是否为NULL

fb0cc24487d9448289e0ac175d8333be.png

我们接上不同点5,malloc申请空间可能会失败。所以我们要分类讨论malloc申请空间的情况

1.失败返回NULL(空指针)。

2.成功返回申请到空间的首地址。

至于perror是一种打印申请空间失败原因的库函数,我们可写可不写,为了可读性最好加上,接着如果失败我们return 1结束程序。因为以及申请失败了,下面的代码是针对成功的情况,如果不结束程序,代码就会出错。

 9bb6ee7f7f094c9dbd5a88e62f78cb24.png

for循环将0到9输入到这片空间中,并打印到屏幕中,

最后使用完了这块空间,我们free释放掉(free是编译器里的库函数,用来释放某一块空间的),还回去。释放完后free函数并不会将pa置为NULL,为了防止野指针的出现,我们需要手动设为NULL.

778302513ac743838f3e96d42e4f4baf.png

2.calloc详解

calloc和malloc很类似也是申请一块空间,我们接着看。

calloc的头文件是#include <sdtlib.h>calloc - C++ Reference (cplusplus.com)

我们可以点进看看的calloc的详细内容

f46de5c5d65f49d69189099f1fb19707.png

同样我们可以看到calloc的返回值是void*,但calloc函数比malloc多了一个参数。我们具体分析

194835d2bdfc40aa9afec011b6981671.png

具体了解calloc。我们比较calloc与malloc

相同点:

1.都是向堆区申请一块空间。

2.都是动态的,可变的。

3.成功返回这块空间的首地址,失败返回NULL。

4.函数返回值都是void*。

不同点:

1.申请的空间成功时可以初始化为0,而malloc不可以。

至于不同点,我们看代码

​
​
#include <stdlib.h>
int main()
{
	int* pa =(int *)calloc(10 , sizeof(int));
	if (pa == NULL)
	{
		perror("calloc:");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(pa+i));
	}
	free(pa);
	pa = NULL;
	return 0;
}

​

​

我们没有给calloc申请的空间赋值,我们看结果是

14578fd50b9b4057a61f63056bca345e.png

申请空间后初始化为0。

3.realloc详解

realloc的头文件是#include <sdtlib.h>realloc - C++ Reference (cplusplus.com)

我们可以点进看看的calloc的详细内容

a37387374e5144e3803092551cdd7b8f.png

看功能,realloc是来调整malloc/calooc申请的空间。与数组的不同就体现在这。

具体分析realloc的两个参数:

ad2be7e231fa40058d6c6673b3be2dea.png

具体我们看代码操作:
 

​
#include <stdlib.h>
int main()
{
	int* pa = (int*)malloc(5 * sizeof(int));
	if (pa == NULL)
	{
		perror("mallco:");
		return -1;
	}
	for (int i = 0; i < 5; i++)
	{
		*(pa + i) = i;//pa需要+i指向下一个位置。
		printf("%d ", *(pa + i));
	}
	int* pb = (int*)realloc(pa, 10 * sizeof(int));
	if (pb == NULL)
	{
		pb = pa;
		free(pb);
		pb = NULL;
		perror("realloc:");
		return 1;
	}
	else
		pa = pb;
	for (int i = 5; i < 10; i++)
	{
		*(pa + i) = i;//pa需要+i指向下一个位置。
		printf("%d ", *(pa + i));
	}
	free(pa);
	pa = NULL;
	return 0;
}

​

代码上半部分用malloc申请一块空间后,我们觉得20字节大小不够,我们就使用realloc函数增大空间至40个字节大小。同样申请完后我们要判断申请是否成功。

bf37312dedff44bb9c164f4c8c725450.png

这里realloc比较复杂。我们一一述说:
1.失败返回NULL。

2.成功有分为两种情况

  1. 在申请时太大占用了其它已经占用空间时realloc会在内存的堆区重新找一个满足条件的空间,同时把旧的数据copy到新的空间,接着释放旧空间,同时返回新空间的起始地址。
  2. 在申请时空间够用时,返回起始地址。

所以如果pb==NULL时申请失败,我们需要把之前malloc申请的空间释放掉。并置为NULL。

总结:malloc,calloc,realloc三者都是void*类型函数,接收返回值时都要强制类型转换。在堆上申请的空间要即使释放,并置为空指针。每次申请完后要判断申请是否成功等等。

以上希望能够帮到你,让你对动态内存管理有跟深的理解。

  • 33
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
malloc、callocrealloc都是C语言中用于动态内存分配的函数,它们之间的区别如下: 1. malloc函数:用于分配指定大小的内存块,返回指向该内存块起始地址的指针。该函数只分配内存,不会对内存进行初始化。 2. calloc函数:用于分配指定数量、指定大小的内存块,返回指向该内存块起始地址的指针。该函数会将分配的内存块全部初始化为0。 3. realloc函数:用于重新分配之前已经分配的内存块的大小,返回指向该内存块起始地址的指针。如果原先分配的内存块大小不足以存储新的数据,realloc函数会重新分配一块新的内存块,并将原先内存块中的数据复制到新的内存块中,然后释放原先的内存块。 下面是三个函数的使用示例: 1. malloc函数的使用示例: ```c #include <stdio.h> #include <stdlib.h> int main() { int *p = (int*)malloc(sizeof(int)); // 分配一个int类型的内存块 if (p == NULL) { printf("malloc failed\n"); return -1; } *p = 10; // 给内存块赋值 printf("%d\n", *p); // 输出内存块的值 free(p); // 释放内存块 return 0; } ``` 2. calloc函数的使用示例: ```c #include <stdio.h> #include <stdlib.h> int main() { int *p = (int*)calloc(1, sizeof(int)); // 分配一个int类型的内存块,并将其初始化为0 if (p == NULL) { printf("calloc failed\n"); return -1; } printf("%d\n", *p); // 输出内存块的值 free(p); // 释放内存块 return 0; } ``` 3. realloc函数的使用示例: ```c #include <stdio.h> #include <stdlib.h> int main() { int *p = (int*)malloc(sizeof(int)); // 分配一个int类型的内存块 if (p == NULL) { printf("malloc failed\n"); return -1; } *p = 10; // 给内存块赋值 printf("%d\n", *p); // 输出内存块的值 p = (int*)realloc(p, sizeof(int) * 2); // 重新分配内存块的大小 if (p == NULL) { printf("realloc failed\n"); return -1; } *(p + 1) = 20; // 给新的内存块赋值 printf("%d %d\n", *p, *(p + 1)); // 输出两个内存块的值 free(p); // 释放内存块 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值