引用头文件
stdlib.h
内存使用的方式
创建变量(开辟一块独立的空间)
创建数组(开辟一块连续的 空间)
上述开辟空间的方式有两个特点
存在的问题
函数原型
void* malloc (size_t size);
函数功能
函数返回值
函数用例
#include
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
//malloc 返回的是 void* 的指针,需要转换成对应的指针类型才能使用
return 0;
}
函数原型
void* calloc (size_t num, size_t size);
函数功能
函数用例
函数原型
void* realloc (void* ptr, size_t size);
函数功能
函数参数
realloc 函数的两种使用情况
void* realloc (void* ptr, size_t size);
void* realloc(NULL,size_t size);
函数用例
realloc 调整空间的方式
realloc在调整内存空间时存在两种情况
函数原型
void free (void* ptr);
函数参数
函数功能
函数用例
int main()
{
int* p1 = (int*)malloc(10 * sizeof(int));
int* p2 = (int*)calloc(10, sizeof(int));
int* p3 = (int*)realloc(NULL, sizeof(int) * 10);
//......
free(p1);
free(p2);
free(p3);
return 0;
}
注意事项
int main()
{
int* ptr = (int*)malloc(10 * sizeof(int));
//......
free(ptr); //释放掉ptr指向的空间后,ptr内存的地址值未变,还是记得原来空间的地址
ptr = NULL; //因此要主动修改ptr内存放的地址值为NULL
return 0;
}
int* p = (int*)malloc(40);
*p = 20;//使用前为判断指针 p 内的值是否有效
正确做法
int* p = (int*)malloc(40);
if (NULL == p) //使用之前先判断该空间是否开辟成功
{
return 1; //1 为异常返回
}
*p = 20;
int* p = calloc(10, sizeof(int));
if (NULL == p)
{
perror("calloc");
return 1;
}
for (int i = 0; i <= 10; i++)//当 i 到 10 时越界访问
{
printf("%d ", *(p + i));
}
free(p);
p = NULL;
int* p = (int*)malloc(10 * sizeof(int));
//......
free(p);//此时已经释放过该空间一次
//.....
free(p);//睡蒙了又释放一次
解决办法
void test()
{
int* p = (int*)malloc(10 * sizeof(int));
//p 是局部变量,出了作用域就销毁,等这个函数一结束就没人再记得这块空间的起始地址了
if (true)//此时动态开辟的空间永远没机会释放了
{
return;
}
free(p);
p = NULL;
}
int main()
{
test();
return 0;
}
struct S
{
char c;
int i;
int arr[]; //未知大小数组 - 柔性数组成员
};
柔性数组的特点
struct S
{
char c;
int i;
int arr[];
};
int main()
{
struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
//这 20 个字节才是分配给柔性数组 arr 的
return 0;
}
第一步
int** p = (int**)malloc(sizeof(int*) * 3);
第二步
for(int i = 0; i < 3; i++)
{
*(p + i) = (int*)malloc(sizeof(int) * 5);
}