目录
一、动态内存管理
1、常用函数
(1)malloc与free
这两个函数都在头文件stdlib.h中包含。
函数原型


参数
malloc参数是size_t类型的size,代表了申请的地址大小(单位是字节)。
free参数是void类型的指针,指向想释放的内存。
返回值

malloc函数当分配内存成功时会返回指向内存的指针(类型是void*),所以我们要将返回的值转化为我们想要的指针类型。
当申请失败时,返回值是NULL(这里可以通过检验是不是NULL来判断是否分配内存成功)。
我们举一个例子:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
//例如我们想申请十个整形的空间
int* arr = (int*)malloc(10 * sizeof(int));
if (arr == NULL)
{
perror("malloc");
return 1;
}
free(arr);
arr=NULL;
//将指针置为空
return 0;
}

free函数没有返回值
使用的注意事项
1、一定要将malloc返回的值强制类型转换为我们想要的指针类型。
int* arr = (int*)malloc(10 * sizeof(int));
2、要注意,在C语言中,使用malloc函数申请的空间是不会自动释放的,我们一定要在使用malloc申请空间后再使用free释放(虽然在程序结束后申请的空间会自动回收,但是考虑到在工作中内存泄漏的后果很严重,所以还是要规范操作),而且同一块空间不能释放两次。
进阶使用
我们以可以使用malloc来申请类似于二维数组的空间,示例如下:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
//例如我们想申请arr[3][5]的空间
int** arr = (int**)malloc(3 * sizeof(int*));
if (arr == NULL)
{
perror("malloc");
return 1;
}
for (int i = 0; i < 3; i++)
{
*(arr + i) = (int* )malloc(5 * sizeof(int));
//依次申请指针指向的空间
if (*(arr + i) == NULL)
{
perror("malloc-2");
//申请失败释放掉已申请空间,防止内存泄露
for (int j = i; j >= 0; j--)
{
free(*(arr + j));
}
free(arr);
return 1;
}
}
for (int i = 0; i < 3; i++)
{
free(*(arr + i));
}
free(arr);
return 0;
}
常见问题
最好不要在函数中使用malloc为一个指针变量申请空间,因为函数的内容是在栈空间中的,在出函数时会直接销毁,如果在主函数中使用在函数中申请的指针变量就会找不到对应的空间。
错误代码如下:
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
这里我采用传址调用的方法改进:
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
传实参p的地址过去,在函数中直接通过地址来改变实参的值。
(2)calloc与realloc
calloc函数

realloc函数
1、ptr指的是想扩容的内容
2、size指的是想扩容的字节数
3、返回值是扩容后的地址
4、在扩容的时候,会将数据迁移到新的内存中
但是这里又分两种情况:
如果是情况1,则直接将扩容的内存加到原有的内存后面
如果是情况2,则在找一块内存进行分配
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr = (int*)malloc(100);
if (ptr != NULL)
{
//业务处理
}
else
{
return 1;
}
//扩展容量
//代码1 - 直接将realloc的返回值放到ptr中
ptr = (int*)realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?)
//代码2 - 先将realloc函数的返回值放在p中,不为NULL,在放ptr中
int* p = NULL;
p = realloc(ptr, 1000);
if (p != NULL)
{
ptr = p;
}
//业务处理
free(ptr);
return 0;
}
(3)柔性数组
柔性数组是在C99标准中新添加的概念
struct num
{
int a;
int arr[];
};
int main()
{
struct num* arr = malloc(sizeof(struct num));
//只申请了int类型a的值
struct num* ret = NULL;
ret = realloc(arr, sizeof(struct num) + 5 * sizeof(int));
if (ret != NULL)
{
arr = ret;
ret=NULL;
}
free(arr);
return 0;
}
985

被折叠的 条评论
为什么被折叠?



