🎬 鸽芷咕:个人主页 🔥 个人专栏:《C语言初阶篇》 《C语言进阶篇》
⛺️生活的理想,就是为了理想的生活!
🌈hello! 各位宝子们大家好啊,又是新的一天开始了,今天给大家带来的是动态内存规划这一章节! ⛳️我们在创建变量的时候大家都知道大小是固定,不够灵活。而动态内存分配可以改变这一现象!当我们需要多少就可以规划多少,而不需要时就可以释放掉,这样是不是就可以极大地避免了内存的浪费! 📚本期文章收录在《C语言高阶篇》,大家有兴趣可以看看呐! ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!
⛳️在前面内容中我们学的开辟空间大多都是用数据类型直接创建空间。
int main()
{
int a = 0;//在栈空间上开辟四个字节
int arr[40]={0};//在栈空间上开辟40个字节
}
但是这的开辟空间的方式有两个缺点:
所以像以前的空间开辟方法满足不了我们的需求,那么有没有我们想开辟多少空间就开辟多少,而当我们不想要的时候还可以释放!这个时候就需要动态内存开辟了!
⛳️ 而动态内存开辟就需要用到相关的函数分别是:
malloc
free
calloc
realloc
把这四个函数只要掌握就可以完全的掌握动态内存分配了,下面我们就详细给大家介绍介绍:
动态内存开辟的函数: malloc
void* malloc (size_t size);
这个函数向内存申请一块 连续可用
的空间,并返回指向这块空间的指针。
void*
,所以 malloc
函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。size
为 0
,malloc
的行为是标准是未定义的,取决于编译器。⛳️ 好了malloc的使用方法给大家介绍了,接下来就是给大家介绍介绍这个这个函数如何使用:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
malloc(40);
return 0;
}
我们都知道数组创建的空间是连续,而malloc申请的空间也是连续的但是malloc的空间是没有类型的。
malloc
的返回值类型强制转换为 int*
malloc
的返回值就可以#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p=(int*)malloc(40);
}
这样我们就可以和整形数组一样存放整形了,因为指针解引用每次也跳过4个字节
如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
p
返回NULL 空指针。int main()
{
int arr[10] = { 0 };
int* p = (int*)malloc(40);
//开辟失败
if (p == NULL)
{
perror("malloc");
return 1;
}
return 0;
这样就就可以在开辟失败时及时避免错误,直接return返回让程序结束!
perror
给我们提示一下malloc
里面出现了什么错误!📑图片展示:
⛳️ 大家看这里当我们申请的空间太大是开辟不了就会给我们返回空间不够的错误提示
⛳️我们都知道临时变量是存放在栈空间的,那么malloc申请的空间是哪里的呢?
📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = (int*)malloc(40);
//开辟失败
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
return 0;
}
📑 代码结果:
⛳️这里打印的就是我们申请空间的值,但由于malloc函数并不会给我们初始化所以里面存放的都是随机值。
⛳️我们动态内存分配都是在堆区开辟空间的,
p
指针变量是在栈区里面开辟的空间里面。所以当malloc在返回时返回了起始地址然后我们用 p 接收了malloc申请空间的起始地址
⛳️ 做为一个程序员我们在想要申请空间的时候肯定是已经知道,要申请多少空间。你又要malloc申请空间,又只申请0个空间,这种行为本来就是不合理,所以我们在使用malloc时要避免这种情况以免出现不必要的错误!
size
为0,malloc
的行为是标准是未定义的,取决于编译器。⛳️而malloc申请的空间,当程序退出时,才会还给操作系统,而当程序未结束时,动态内存申请的内存空间,是不会主动释放的。这样就会照成内存的浪费!
⛳️C语言提供了另外一个函数 free ,专门是用来做动态内存的释放和回收的,函数原型如下:
free函数用来释放动态开辟的内存。
⛳️ 好了free的参数详情给大家介绍了,接下来就是给大家介绍介绍这个这个函数如何使用:
📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = (int*)malloc(40);
//开辟失败
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
free(p);
p = NULL;
return 0;
}
⛳️ 这就是
free
的使用方法了,是不是非常简单。只需要把我们指针变量p
传给free
函数,因为p
里面存放了malloc
申请空间的起始地址,那么为什么还要把 p 给置为空指针呢?
如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
📚 代码演示:
int main()
{
int a = 10;
int* p = &a;
free(p);//err
return 0;
}
📑 代码结果:
⛳️ C语言还提供了一个函数叫
calloc
,calloc
函数也用来动态内存分配。其实非常简单这个函数和malloc
的功能是一样的,只不过会把申请的空间初始化为0
✅函数原型如下:
void* calloc (size_t num, size_t size);
📜举个例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = calloc(10,sizeof(arr[0]));
//开辟失败
if (p == NULL)
{
perror("calloc");
return 1;
}
//开辟成功
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
free(p);
p = NULL;
return 0;
}
📑 代码结果:
⛳️ 这里就不给大家过多描述了,这个函数和malloc的使用大致一样!好的习惯是每次申请的动态空间在用完的时候都要释放掉!
⛳️有人会说不是动态内存可大可小嘛?想要多少空间就要多少,不想要了就可以缩小!前面的函数只能开辟和释放并不能控制大小啊?下面我们就给大家介绍介绍realloc函数它就完美的实现了这些功能。
realloc 函数函数原型如下:
void* realloc (void* ptr, size_t size);
realloc函数的出现让动态内存管理更加灵活: void* realloc (void* ptr, size_t size);
ptr
是要调整的内存地址size
调整之后新大小📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = calloc(10,sizeof(arr[0]));
//开辟失败
if (p == NULL)
{
perror("calloc");
return 1;
}
//开辟成功
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
//增加空间
realloc(p, 80);
free(p);
p = NULL;
return 0;
}
这就是realloc的用法当我们说开辟的空间只有40个大小不够用了。那么就可以用realloc去增加为80个字节大小!
⛳️ 第一种情况就是后面的连续空间足够,我们我们就会在后给连续的新开辟40个字节使其增加为80个字节大小!
📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = calloc(10,sizeof(arr[0]));
//开辟失败
if (p == NULL)
{
perror("calloc");
return 1;
}
//开辟成功
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
//增加空间
realloc(p, 80);
free(p);
p = NULL;
return 0;
}
📑图片展示:
这就是第一种情况的内存分布,当后面的空间足够时后给连续的新开辟40个字节使其增加为80个字节大小
⛳️当我们想用reaclloc增加空间时,但是后面空间不够了就会重新开辟新空间并将原来空间的内容拷贝到新空间,并且将旧空间释放掉.
这里我们思考一个问题,realloc也会返回失败那么就会返回NULL空指针!
这样就会造成内存泄漏的问题,所以我们在这里就不敢用p接收我们的realoc返回值,需要进行代码改进!
📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = calloc(10,sizeof(arr[0]));
//开辟失败
if (p == NULL)
{
perror("calloc");
return 1;
}
//开辟成功
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
//增加空间
int* ptr = realloc(p, 80);
if (ptr != NULL)
{
p = ptr;
ptr=NULL;
}
else
{
perror("realloc");
}
free(p);
p = NULL;
return 0;
}
这样就可以避免我们上面说的错误了,如何
realloc
开辟失败我们就不接收空指针。
⛳️ 这个不就更加简单了嘛?前面说了我们realloc函数可以动态开辟空间可大可小!那么使动态内存变小不就是更加简单了嘛?直接把内存改小不就行了.
📚 代码演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = calloc(10,sizeof(arr[0]));
//开辟失败
if (p == NULL)
{
perror("calloc");
return 1;
}
//减少空间
int* ptr = realloc(p, 20);
if (ptr != NULL)
{
p = ptr;
}
else
{
perror("realloc");
}
free(p);
p = NULL;
return 0;
}
📑 代码结果:
⛳️这里就可看到我们把malloc申请的动态空间40个字节,改变成了20个字节!
✅ 归纳:
好了以上就是关于动态内存分配函数 malloc
free
calloc
realloc
4个动态内存分配函数的全部用法了!
malloc的介绍和使用方法
free的介绍和使用方法
calloc和malloc的区别
realloc语句使用的2种情况
☁️ 把这些内存函数掌握完,你就可以完美的使用动态内存分配了快去试试吧!
看到这里了还不给博主扣个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。