目录
知识点1【malloc函数 和 free函数】
malloc函数
#include<stdlib.h>
void *malloc(unsigned int num_size);
形参:num_size需要申请空间大小的字节数。
返回值:
成功:返回空间的起始地址
失败:NULL
特点:
1、对于malloc的返回值 一般要强制类型转换
2、malloc申请的空间 内容不确定 一般使用memset进行清空
3、多次调用malloc 第1次malloc 和 第2次malloc的地址不一定连续
free函数
void free(void *addr);
释放堆区空间
案例1:从堆区申请 一个int空间
void test02()
{
int *addr = NULL;
addr = (int *)malloc(sizeof(int));
if(addr == NULL)//申请失败了
{
printf("malloc err\n");
return;
}
printf("*addr=%d\n", *addr);//不确定的值
//对堆区空间 清0
memset(addr, 0, sizeof(int));
printf("*addr=%d\n", *addr);//0
//对addr的空间 就行写 或 读
*addr = 1000;//写
printf("*addr=%d\n", *addr);//1000 读
//释放堆区空间 空间使用权限的回收 是否对空间内容清0 这是不确定的
free(addr);
}
int main(int argc,char *argv[])
{
test02();
return 0;
}
运行结果:
案例2:从堆区申请一个数组 数组的大小 由用户决定
1、从键盘获取 用户要申请的数组大小
2、根据大小 从堆区申请空间
3、对空间的读写操作
4、释放该空间
void test03()
{
int n = 0;
int i=0;
int *arr=NULL;
//1、获取用户大小
printf("请输入元素的个数:");
scanf("%d", &n);
//2、根据大小从堆区申请空间
arr = (int *)malloc(n*sizeof(int));
if(NULL == arr)
{
//perror 错误输出
perror("mallac");
return;
}
//对arr的读写操作
printf("请输入%d个int数据\n",n);
for(i=0;i<n; i++)
{
scanf("%d", arr+i);
}
//遍历数组
for(i=0;i<n;i++)
{
printf("%d ", arr[i]);
}
//释放空间
free(arr);
}
int main(int argc,char *argv[])
{
test03();
return 0;
}
案例3:从堆区申请一个数组 数组的大小 由用户决定(函数版本)
int get_n(void)
{
int n = 0;
printf("请输入元素的个数:");
scanf("%d", &n);
return n;
}
int* get_addr(int n)
{
return (int *)malloc(n*sizeof(int));
}
void my_input_array(int *arr, int n)
{
int i=0;
//记得将arr指向的空间清0
memset(arr,0,n*sizeof(int));
//获取键盘输入
printf("请输入%d个int数据\n",n);
for(i=0;i<n; i++)
{
scanf("%d", arr+i);
}
}
void my_print_array(int *arr, int n)
{
int i=0;
for(i=0;i<n;i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void test04()
{
int *arr=NULL;
int n = 0;
//得到用户输入的元素个数
//1、获取用户大小
n = get_n();
//定义函数 给arr申请堆区空间
arr = get_addr(n);
if(arr == NULL)
{
perror("get_addr");
return;
}
//对空间读写操作
my_input_array(arr, n);
//对空间数组遍历
my_print_array(arr, n);
//释放空间
free(arr);
}
int main(int argc,char *argv[])
{
test04();
return 0;
}
运行结果:
知识点2【calloc函数】
#include<stdlib.h>
void * calloc(size_t nmemb,size_t size);
参数:
1、nmemb 申请的数据块数
2、size 每一块大小
3、所以申请总大小=nmemb * size
返回值:
成功:返回空间的起始地址
失败:返回NULL
特点:申请的空间自动清零
案例:
void test04()
{
int n = 0;
int i=0;
int *arr=NULL;
//1、获取用户大小
printf("请输入元素的个数:");
scanf("%d", &n);
//2、根据大小从堆区申请空间
#if 0
arr = (int *)malloc(n*sizeof(int));
if(NULL == arr)
{
//perror 错误输出
perror("mallac");
return;
}
memset(arr,0,n*sizeof(int));//清零
#endif
#if 1
arr=(int *)calloc(n, sizeof(int));//自动清零 不需要使用memset
if(NULL == arr)
{
//perror 错误输出
perror("calloc");
return;
}
#endif
//对arr的读写操作
printf("请输入%d个int数据\n",n);
for(i=0;i<n; i++)
{
scanf("%d", arr+i);
}
//遍历数组
for(i=0;i<n;i++)
{
printf("%d ", arr[i]);
}
//释放空间
free(arr);
}
知识点4【realloc动态追加或减少空间】
#include<stdlib.h>
void* realloc(void *s, unsigned int newsize);
功能:
在原先s指向的内存基础上重新申请内存,新的内存的大小为 new_size 个 字节,如果原先内存后面有足够大的空间,就追加,如果后边的内存不 够用,则realloc函数会在堆区找一个newsize个字节大小的内存申请,将原先内存中的内容拷贝过来,然后释放原先的内存,最后返回新内存的地址。
参数:
s:原先开辟内存的首地址
newsize:新申请的空间的大小
返回值:
新申请的内存的首地址
注意:一定要保存 realloc的返回值
void test06()
{
int *arr = NULL;
int n = 0;
int i=0;
int n_new = 0;
//1、获取用户大小
printf("请输入元素的个数:");
scanf("%d", &n);
arr=(int *)calloc(n, sizeof(int));//自动清零 不需要使用memset
if(NULL == arr)
{
//perror 错误输出
perror("calloc");
return;
}
printf("请输入%d个int数据\n",n);
for(i=0;i<n; i++)
{
scanf("%d", arr+i);
}
//遍历数组
for(i=0;i<n;i++)
{
printf("%d ", arr[i]);
}
//再追加5个元素
printf("请输入新增的元素个数:");
scanf("%d", &n_new);
arr = (int *)realloc(arr, (n+n_new)*sizeof(int));
printf("请输入新增的%d个int数据\n",n_new);
for(i=n;i<(n+n_new); i++)
{
scanf("%d",arr+i);
}
for(i=0;i<(n+n_new);i++)
{
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
}
int main(int argc,char *argv[])
{
test06();
return 0;
}
运行结果:
知识点5【堆区空间使用的注意事项】
void test08()
{
int *p2 = NULL;
int *p3 = NULL;
//1、指向堆区空间的指针变量 不要随意的更改指向
int *p=(int *)calloc(1,sizeof(int));
int num = 10;
p = #//p指向num 导致calloc申请的空间泄露
//2、不要操作已经释放的空间
p2 = (int *)calloc(1,sizeof(int));
*p2 = 1000;
//释放该空间
free(p2);
printf("*p2 = %d\n", *p2);//不确定
//3、不要对堆区空间重复释放
p3 = (int *)calloc(1,sizeof(int));
free(p3);
free(p3);//多次释放
}
知识点6【防止多次释放】
void test09()
{
int *p = (int *)calloc(1,sizeof(int));
if(p != NULL)//防止多次释放
{
free(p);
p=NULL;
}
if(p != NULL)
{
free(p);
p=NULL;
}
}