亲爱的读者,大家好!我是一名正在学习编程的高校生。在这个博客里,我将和大家一起探讨编程技巧、分享实用工具,并交流学习心得。希望通过我的博客,你能学到有用的知识,提高自己的技能,成为一名优秀的程序员。如果你有任何疑问或建议,请随时在评论区留言,让我们一起成长进步!现在,让我们开始这场知识之旅吧!
🚀个人主页:FEN03
📚收入专栏:C语言
文章目录
- 📚前言
- 📘1. 为什么要动态内存分配❓
- 📗2. 如何去动态内存开辟❓
- 🔖2.1 malloc
- 🔖2.2 free
- 🔖2.3 calloc
- 🔖2.4 realloc
- 👋结束语
📚前言
为什么需要动态内存开辟,如何向内存申请空间?接下来,就让我们去探讨吧~
📘1. 为什么要动态内存分配❓
在先前,我们开辟内存的方法无非是在栈区创建一个变量,或者说一个数组。
#include<stdio.h>
int main()
{
int a = 0; //在栈区开辟了4个字节的空间
int arr[10] = { 0 }; //在栈区开辟了40个连续字节的空间
return 0;
}
这2种内存开辟,都存在着2种特点:
- 内存开辟的大小是固定的了。
- 数组在创建时,必须是指定它的长度,一旦确定大小后不能再进行更改。
为了迎合更高的要求,上述的情况就不能满足了。那么为了解决这一问题,C语言引入了动态内存开辟,这样程序员就可以灵活的去申请和释放空间。
那么接下来就让我们探索如何去动态的向内存开辟。
📗2. 如何去动态内存开辟❓
那么为了实现动态内存的开辟,C语言提供了4个函数,那么接下来,就让我们去学习如何使用这些函数吧~⬇️
🔖2.1 malloc
为了实现动态内存开辟,C语言提供了malloc函数。
函数语法形式:
void* malloc (size_t size);
这个函数能够向内存开辟一块连续可用的空间,并且会返回指向这块内存空间的指针。
- 如果内存开辟成功,则会返回指向这块开辟好的内存的指针。
- 如果内存开辟失败,则会返回NULL,所以当我们使用malloc函数时,一定要检查是否开辟成功。
- malloc函数的返回类型是void* ,这是因为malloc函数并不知道程序员要开辟内存空间的类型,所以当程序员使用时由自己决定返回类型。
- 如果size为0,这一行为是标准未定义的,而且也没必要,最终的结果也是编译器决定的。
使用malloc函数需要包含头文件:
#include<stdlib.h>
我们可以使用malloc来开辟下内存空间:
#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函数的原型如下:
void free (void* ptr);
- 如果参数ptr指向的内存空间不是动态内存开辟的,那么free函数的行为是未定义的。
- 如果参数ptr是NULL,则函数什么事都不做。
free和malloc所包含的头文件一样。
#include<stdlib.h>
如何与malloc搭配使用❓❓❓
代码如下:
#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函数原型:
void* calloc (size_t num, size_t size);
- 函数有2个参数,第一个 num 为个数,第二个 size 为字节大小,那么它会开辟程序员所要求的内存空间,并且把空间的每一个字节初始化为0(malloc,值都是cd(随机值))。
- 当内存开辟成功,返回的是指向该内存的指针;失败时,返回NULL ,所以当我们使用时,也和malloc一样,需要检查。
calloc函数如何向内存申请空间呢?让我们接着往下看⬇️⬇️⬇️
当我需要向内存申请40个字节大小时:
#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函数原型:
void* realloc (void* ptr, size_t size);
- ptr是需要调整的内存地址
- size是调整后的大小
- 返回值为调整后的内存起始位置
- 这个函数调整会在原内存空间的基础上,还会将原来内存中的数据移动到新的内存空间
- realloc函数在调整内存空间时,会分为2中情况:
情况1:当原有空间之后有着足够大的空间,那么就会在原有空间的基础上,调整大小。
情况2:当原有空间之后没有足够大的空间,那么会另开辟一块新的空间,并且把原有空间移到新空间,再进行调整,原有空间会被释放
那么如何使用realloc函数开辟内存空间? 接着往下看吧~⬇️⬇️⬇️
#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个字节。
👋结束语
非常感谢您花时间阅读我的博客,希望我的分享能为您带来收获。如果您对本文有任何想法或疑问,欢迎在评论区留言交流。如果您喜欢我的博客,请继续关注,我会定期更新更多精彩内容。最后,别忘了行动起来的力量,让我们一起实践这些方法,见证自己的成长和进步!
那么到此,关于动态内存开辟就讲解完了~
再见,祝您生活愉快!