15. 《C语言》——【如何动态内存开辟】

亲爱的读者,大家好!我是一名正在学习编程的高校生。在这个博客里,我将和大家一起探讨编程技巧、分享实用工具,并交流学习心得。希望通过我的博客,你能学到有用的知识,提高自己的技能,成为一名优秀的程序员。如果你有任何疑问或建议,请随时在评论区留言,让我们一起成长进步!现在,让我们开始这场知识之旅吧!



🚀个人主页: FEN03

📚收入专栏: C语言



文章目录

  • 📚前言
  • [📘1. 为什么要动态内存分配❓](#📘1. 为什么要动态内存分配❓)
  • [📗2. 如何去动态内存开辟❓](#📗2. 如何去动态内存开辟❓)
    • [🔖2.1 malloc](#🔖2.1 malloc)
    • [🔖2.2 free](#🔖2.2 free)
    • [🔖2.3 calloc](#🔖2.3 calloc)
    • [🔖2.4 realloc](#🔖2.4 realloc)
  • 👋结束语

📚前言

为什么需要动态内存开辟,如何向内存申请空间?接下来,就让我们去探讨吧~


📘1. 为什么要动态内存分配❓


在先前,我们开辟内存的方法无非是在栈区创建一个变量,或者说一个数组。

c 复制代码
#include<stdio.h>
int main()
{
	int a = 0; //在栈区开辟了4个字节的空间
	int arr[10] = { 0 }; //在栈区开辟了40个连续字节的空间
	return 0; 
}

这2种内存开辟,都存在着2种特点

  1. 内存开辟的大小是固定的了。
  2. 数组在创建时 ,必须是指定它的长度,一旦确定大小后不能再进行更改

为了迎合更高的要求,上述的情况就不能满足了。那么为了解决这一问题,C语言引入了动态内存开辟,这样程序员就可以灵活的去申请和释放空间。

那么接下来就让我们探索如何去动态的向内存开辟。


📗2. 如何去动态内存开辟❓

那么为了实现动态内存的开辟,C语言提供了4个函数,那么接下来,就让我们去学习如何使用这些函数吧~⬇️


🔖2.1 malloc

为了实现动态内存开辟,C语言提供了malloc函数。

函数语法形式:

c 复制代码
void* malloc (size_t size);

这个函数能够向内存开辟一块连续可用的空间,并且会返回指向这块内存空间的指针。

  1. 如果内存开辟成功,则会返回指向这块开辟好的内存的指针。
  2. 如果内存开辟失败,则会返回NULL,所以当我们使用malloc函数时,一定要检查是否开辟成功。
  3. malloc函数的返回类型是void* ,这是因为malloc函数并不知道程序员要开辟内存空间的类型,所以当程序员使用时由自己决定返回类型。
  4. 如果size为0,这一行为是标准未定义的,而且也没必要,最终的结果也是编译器决定的。

使用malloc函数需要包含头文件:

c 复制代码
#include<stdlib.h>

我们可以使用malloc来开辟下内存空间:

c 复制代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	//使用if语句来判断是否开辟成功,如果失败则提示错误信息以及提前结束
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//...... 

	return 0; 
}

我们进行调试看看是否开辟成功?

我们看到已经内存开辟成功了,这些值都是cd,也就是一些随机值。

但是malloc只是这样使用吗,其实并不是,malloc是需要搭配free函数使用的。接下来,就让我们介绍free函数吧~ ⬇️


🔖2.2 free

C语言提供了free函数,那么free函数有什么用❓,我们在前边介绍了malloc函数,是用来向内存申请空间的,那么free函数就是专门用来对动态内存开辟的空间进行释放和回收。

在生活中,我们都知道有借有还,再借不难。那么在内存中也是这个道理。


free函数的原型如下:

c 复制代码
void free (void* ptr);
  1. 如果参数ptr指向的内存空间不是动态内存开辟的,那么free函数的行为是未定义的。
  2. 如果参数ptr是NULL,则函数什么事都不做。

free和malloc所包含的头文件一样。

c 复制代码
#include<stdlib.h>

如何与malloc搭配使用❓❓❓

代码如下:

c 复制代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//使用...... 

	//释放内存空间
	free(p); 
	p = NULL; 

	return 0; 
}

这样free函数就能够释放p所指向的动态内存开辟的内存空间,那么为什么还需要把p置为NULL呢?

是因为,free函数虽然已经释放掉了开辟的内存空间,但是指针p还是指向这一空间,为了避免野指针,所以置为了NULL。


🔖2.3 calloc

动态内存开辟的函数不仅仅是malloc函数,C语言还提供了另一种函数:calloc

calloc函数原型:

c 复制代码
void* calloc (size_t num, size_t size);
  1. 函数有2个参数,第一个 num 为个数 ,第二个 size 为字节大小 ,那么它会开辟程序员所要求的内存空间,并且把空间的每一个字节初始化为0(malloc,值都是cd(随机值))。
  2. 当内存开辟成功,返回的是指向该内存的指针;失败时,返回NULL ,所以当我们使用时,也和malloc一样,需要检查。

calloc函数如何向内存申请空间呢?让我们接着往下看⬇️⬇️⬇️

当我需要向内存申请40个字节大小时:

c 复制代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//calloc向内存申请40个字节空间  
	int* p  = (int*)calloc(10, sizeof(int)); 
	//判断是否开辟成功
	if (p == NULL)
	{
		perror("calloc"); 
		return 1; 
	}
	//使用..... 
	

	//释放内存空间
	free(p); 
	p = NULL;    
	return 0;
}

结果如何? 让我们来调试看看吧~

我们观察到,calloc函数向内存开辟的40个字节成功,并且每一个字节初始化为0。

calloc函数和malloc函数都是向内存申请空间,既然是申请,那么也需要归还内存空间,一样的都是需要free函数释放把内存还给系统。


🔖2.4 realloc

在前边,我们介绍了malloc函数和calloc函数以及free函数,最后我们介绍realloc函数。

那么我们需要先了解,realloc函数有什么用存在的意义是什么?

其实是为了让动态内存开辟更加的灵活,有时候,我们使用malloc或者calloc申请内存空间时,可能到某一时间段发现空间太大了或者不够用小了。

那么为了对内存空间进行调整,C语言呢就提供了realloc函数,这样我们就可以对内存的大小进行灵活的调整。


realloc函数原型:

c 复制代码
void* realloc (void* ptr, size_t size);
  1. ptr是需要调整的内存地址
  2. size是调整后的大小
  3. 返回值为调整后的内存起始位置
  4. 这个函数调整会在原内存空间的基础上,还会将原来内存中的数据移动到新的内存空间
  5. realloc函数在调整内存空间时,会分为2中情况:
    情况1:当原有空间之后有着足够大的空间,那么就会在原有空间的基础上,调整大小。
    情况2:当原有空间之后没有足够大的空间,那么会另开辟一块新的空间,并且把原有空间移到新空间,再进行调整,原有空间会被释放

那么如何使用realloc函数开辟内存空间? 接着往下看吧~⬇️⬇️⬇️

c 复制代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
	//malloc向内存开辟40个字节
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//发现不够用,那么使用realloc函数调整内存大小
	//调整为80个字节
	int* ptr = (int*)realloc(p, 20 * sizeof(int));  
	if (ptr != NULL)
	{
		p = ptr; 
		ptr = NULL;  
	}
	else
	{
		perror("realloc"); 
		return 1; 
	}

	//使用..... 



	//释放内存空间
	free(p);
	p = NULL;

	return 0;
}

是否开辟成功?我们进行调试看看

我们可以看到之前malloc函数开辟的内存为40个字节,经过realloc函数调整大小后,为80个字节。


👋结束语

非常感谢您花时间阅读我的博客,希望我的分享能为您带来收获。如果您对本文有任何想法或疑问,欢迎在评论区留言交流。如果您喜欢我的博客,请继续关注,我会定期更新更多精彩内容。最后,别忘了行动起来的力量,让我们一起实践这些方法,见证自己的成长和进步!

那么到此,关于动态内存开辟就讲解完了~

再见,祝您生活愉快!


相关推荐
tyler_download6 分钟前
golang 实现比特币内核:实现基于椭圆曲线的数字签名和验证
开发语言·数据库·golang
小小小~6 分钟前
qt5将程序打包并使用
开发语言·qt
hlsd#7 分钟前
go mod 依赖管理
开发语言·后端·golang
小春学渗透8 分钟前
Day107:代码审计-PHP模型开发篇&MVC层&RCE执行&文件对比法&1day分析&0day验证
开发语言·安全·web安全·php·mvc
杜杜的man11 分钟前
【go从零单排】迭代器(Iterators)
开发语言·算法·golang
亦世凡华、11 分钟前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
测试界的酸菜鱼25 分钟前
C# NUnit 框架:高效使用指南
开发语言·c#·log4j
GDAL25 分钟前
lua入门教程 :模块和包
开发语言·junit·lua
李老头探索27 分钟前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
小沈熬夜秃头中୧⍤⃝27 分钟前
【贪心算法】No.1---贪心算法(1)
算法·贪心算法