我们知道,当创建数组时,空间是固定的,写多少就分配多少空间。
那如果我们想要动态分配空间呢?
目录
一、动态内存的函数
1.1 malloc 函数
这是最经典的动态分配函数,参数就是你想要分配的空间大小
至于void* ,别忘了强转这个好用的功能。
最后别忘了,引头文件<stdlib.h>
来个示例,比如我想动态分配一个40比特大小的空间
int* a = (int*)malloc(40);
但是这里需要一提的是,动态分配有可能会失败,
如果你分配了太大的空间,会导致分配失败,形成空指针。
所以这里需要判断一下。
int* p = (int*)malloc(40);
if (p == NULL)
{
return -1;
}
1.2 free函数
有借有还,再借不难。你借了空间,就要还给我。
那么free函数就是充当这个作用的。用于把刚分配的空间归还给操作系统。
比如我现在就要释放刚刚的p:
free(p);
但 p 释放掉了,p却还在,不会随着free而消失,p还能找到那块空间。
需要我们去手动改为空指针才能化解危险。
free(p);
p = NULL;
1.3 calloc函数
这个函数是把num个size大小的元素先开辟,后初始化为0
总结:calloc函数比malloc函数多个初始化的功能。
int* p2 = (int*)calloc(10, sizeof(int));
if (p2 == NULL)
{
return -1;
}
free(p2);
p2 = NULL;
如上图,10 个 int 的空间就被初始化为0.
1.4 realloc函数
是否有这样一个场景,当你开辟好了一块动态内存空间,
但此时你觉得不够用,想再来点。
realloc函数就是在此刻发挥作用的。
ptr 就是不够用的地址,size就是你要增加的元素大小。
但增加空间我们需要意识到一个问题,如下:
对应写法如下:
p = (int*)realloc(p, 10 * sizeof(int));
对应写法如下:
int* ptr = (int*)realloc(p, 10 * sizeof(int));
if (ptr != NULL)
{
p = ptr;//开辟好后赋过去
}
else
{
return -1;
}
所以我们要考虑周全,不可能一直都是情况二的时候。
所以之后使用realloc函数推荐第二种写法。
二、常见的错误
了解了上面的知识还不够,我们还要了解常见的错误。
2.1 没有判断是否分配成功
void test()
{
int *p = (int*)malloc(40);
//这里要先判断是否分配成功
*p = 20;
free(p);
}
2.2 对动态开辟空间的越界访问
void test()
{
int i = 0;
int *p = (int*)malloc(10*sizeof(int))
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
}
2.3 对非动态开辟的内存使用free
void test()
{
int a = 10;
int *p = &a;
free(p);//错误,free只能用于动态开辟空间
}
2.4 free没有从头开始释放
free使用有个注意点,free释放的对象必须从动态内存的起始位置开始
void test()
{
int *p = (int *)malloc(100);
p++;//这里p就走远了
free(p);//p不再指向动态内存的起始位置
}
2.5 对同一块动态内存多次释放
void test()
{
int *p = (int*)malloc(100);
free(p);
free(p);//重复释放,没有必要
}
2.6 动态开辟内存忘记释放(内存泄漏)
忘记释放 不再使用的动态开辟的空间 会造成内存泄漏
使用的每个动态内存函数都需要free
感谢你能看到这,如有帮助,欢迎点个赞👍。