动态内存分配【C语言】
目录
- 🚠malloc函数和free函数
- 🚜malloc函数介绍
- 💙free函数介绍
- 🚕malloc函数使用
- ❤️calloc函数
- 💛calloc函数介绍
- 💓calloc函数使用
- 💜realloc函数
- 💚realloc函数介绍
- 🌟realloc函数特殊说明
- 💘realloc函数使用
- 💥总结
🚠malloc函数和free函数
🚜malloc函数介绍
👉malloc
函数传送门
malloc
函数是C语言提供给我们的一个动态内存开辟的函数,他的使用形式为:
void* malloc (size_t size);
我们传递给malloc
函数一个无符号整型,malloc
函数申请一段size
大小的内存块,如果申请成功就返回一个指向该内存起始位置的指针,该指针为void*
类型。如果申请失败,则返回一个NULL
指针。
💙free函数介绍
👉free
函数传送门
free
函数和3个动态内存分配函数(malloc
,calloc
,realloc
)总是成对出现的,在需要时进行动态内存分配,在不需要时将动态分配的内存进行释放归还给系统,有借有还,再借不难。如果我们只进行内存申请而不归还,那么系统的内存就会被我们一点一点的吃掉,当一个工程足够大的时候,不进行内存释放可能会造成程序崩溃,带来严重的后果。因此我们应该注意动态申请到的内存在不需要的时候我们要及时释放。
void free (void* ptr);
在释放内存时,我们只需要将指向动态内存申请的空间的指针传递给free
函数即可。
🚕malloc函数使用
malloc
函数的使用介绍我们通过下面的代码来进行介绍,如下代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = NULL;
//动态内存申请
p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
printf("申请失败!\n");
exit(-1);
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
//内存释放
free(p);
p = NULL;
return 0;
}
在代码的开始,我们定义了一个int*
类型的指针,并将其赋值为空,然后通过malloc
函数申请40个字节的空间。(sizeof(int)
计算int
类型的大小)因为malloc
函数返回的是void*
类型的指针,因此我们需要将其进行强制类型转换为int*
类型。
在动态内存申请之后,我们一般都会进行判断,看看是不是申请成功,如果p
指针指向NULL
的话,就表示动态内存申请失败,打印错误信息,结束程序。如果成功则继续接下来的操作。
代码中我们是对申请到的40个字节进行赋值,然后打印,打印完后对内存进行释放,把p
指针传给free
函数,释放完内存后将指针p
置空。打印结果如下图所示:
❤️calloc函数
💛calloc函数介绍
👉calloc
函数传送门
calloc
函数是申请num
个大小为size
的空间并将其赋值为0,申请到的空间总大小为num
*size
个字节,使用格式为:
void* calloc (size_t num, size_t size);
calloc
函数与malloc
函数类似,如果calloc
函数申请内存成功,返回指向该地址起始位置的指针,申请失败的话则返回NULL
,返回指针类型为void*
。
💓calloc函数使用
calloc
函数的使用我们通过以下代码来进行介绍,如下代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = NULL;
//动态内存申请
p = (int*)calloc(10, sizeof(int));
if (p == NULL)
{
printf("申请失败!\n");
exit(-1);
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
//内存释放
free(p);
p = NULL;
return 0;
}
我们还是定义一个int*
类型的指针p
,然后用calloc
函数申请一段num
为10,size
为4的总大小为40个字节的空间,紧接着对指针p
进行判断,为空的话内存申请失败,结束程序。不为空则继续接下来的操作。
代码中我们还是进行赋值操作,然后打印,在打印完之后对内存进行释放,然后将指针p
置为空。我们运行来观察结果,如下图:
我们还可以调试来观察calloc
函数的赋值操作,如下图所示:
可以看到用calloc
函数申请的内存里面全都被置为了0,而我们用malloc
函数申请的内存则为不确定的数,如下图所示:
总的来说,malloc
函数和calloc
函数还是非常相似的,区别在于malloc
函数的参数只有一个,并且申请的内存不进行初始化,而calloc
函数的参数有两个,申请到的空间会进行初始化赋值为0。
💜realloc函数
💚realloc函数介绍
👉realloc
函数传送门
realloc
函数的出现让我们的动态内存管理变得更加灵活,因为有时候我们会觉得在malloc
或者calloc
函数上申请的空间太大了或者太小了,当我们要对内存的大小进行灵活的处理时,realloc
函数就可以对动态内存申请的空间进行调整。函数的原型如下:
void* realloc (void* ptr, size_t size);
realloc
函数有两个参数,第一个为指向需要扩容空间的起始位置的指针ptr
,第二个为调整后的字节大小size
,如果申请成功,返回指向该空间起始位置的指针,类型为void*
,如果失败则返回空指针。
🌟realloc函数特殊说明
realloc
函数进行扩容有两种情况,一种是当原空间的后面拥有足够的空间的时候,扩容时就在该空间的后面进行扩容,如下图所示:
第二种情况为当原空间的后面空间不足以进行扩容操作时,就会在新的空间进行扩容,扩容的大小为原空间和扩容空间之和,并且会将原空间的数据拷贝到扩容后的空间上,然后原空间会主动进行释放,如下图所示:
realloc
函数的第一个参数可以为NULL
,此时的realloc
函数功能相当于malloc
函数。
💘realloc函数使用
realloc
函数使用的介绍我们用一段代码来分析,如下代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = NULL;
//动态内存申请
p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
printf("申请失败!\n");
exit(-1);
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
// 扩容
int* ptr = (int*)realloc(p, 20 * sizeof(int));
if (ptr == NULL)
{
printf("realloc!\n");
exit(-1);
}
p = ptr;
for (i = 10; i < 20; i++)
{
*(p + i) = i;
}
for (i = 0; i < 20; i++)
{
printf("%d ", *(p + i));
}
//内存释放
free(p);
p = NULL;
ptr = NULL;
return 0;
}
我们用malloc
函数进行动态内存申请40个字节,申请成功后给空间进行赋值,后面我们又使用realloc
函数进行扩容,扩容到原来的两倍80个字节,接下来给扩容到的空间继续赋值,然后进行打印,打印完成之后对空间进行释放,然后将指针p
和指针ptr
置为NULL
。运行代码我们来观察结果,如下图所示:
💥总结
动态内存申请的空间都要记得释放,malloc
函数,calloc
函数和realloc
函数总是成对出现的,realloc
函数可以扩容也可以缩小空间,在缩小空间时我们要注意内存的大小要足以放下我们原有的数据。合理运用动态内存申请函数可以帮助我们在管理空间大小上事半功倍,如果觉得文章有帮助的话就给个一键三连吧!有疑问也可以在评论区留言哦!