知识点一:malloc函数和free函数
malloc函数
头文件:#include<stdlib.h>
#include<string.h> // 用于memset函数的头文件
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); ()里面是保存malloc保存返回值的指针变量名
//功能:释放堆区空间
#include<stdio.h>
void test1()
{
int *addr = NULL;
addr = (int *)malloc(sizeof(int)); // (强转类型 *)malloc(n * sizeof(类型)) n:无符号整数 ()里面的字节数是n乘类型的字节数
if(addr == NULL)
{
printf("malloc err\n");
}
printf("*addr = %d\n",addr); //不确定值
//对堆区空间清零
memset(addr,0,sizeof(int));
printf("*addr = %d\n",*addr);
//对addr的空间 进行读 写
*addr = 1000; //写
//读
printf("*addr = %d\n",*addr); //1000
//释放堆区空间 空间使用权限的回收是否对空间内容清0这是不确定的
free(addr);
}
int main(int argc,char *argv[])
{
test1();
}
知识点二:calloc函数
头文件:#include<stdlib.h>
void * calloc(size_t nmemb,size_ t size); // (强转类型 *)calloc(n,sizeof(类型)) n:无符号整数 ()里面的字节数是n乘类型的字节数
参数:
1、nmemb中请的数据块数
2、size 每一块大小
3、申请总大小 = nmemb*size
返回值:
成功:返回空问的起始地址
失败:返回NULL
特点:申请的空间自动清零,不需要memset清零
知识点三:realloc动态追加或减少空间
#include<stdlib.h>
void* realloc(void *S,unsigned int newsize); //(强转类型 *)realloc(保存原先开辟内存的指针名,(原先空间+新增空间)sizeof(类型))
参数:
s:原先开辟内存的首地址
newsize: 新申请的空间的总大小(原先+新增部分大小)(如果新申请的空间比原先大,则是追加,如果比原先小,则是减少)
返回值:新申请的内存的首地址
realloc的返回值一般要强制类型转换再赋值保存(返回值就是开辟对应的空间)
功能:
在原先s指向的内存基础.上重新申请内存,新的内存的大小为new_ size 个字节,如果原先内存后面有足够大的空间,就追加,如果后边的内存不够用,则relloc函数会在堆区找一个newsize个字节大小的内存申请,将原先内存中的内容拷贝过来,然后释放原先的内存,最后返回新内存的地址
知识点四:堆区空间使用的注意事项
void test1()
{
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);//多次释放
}
知识点五:防止多次释放
void test09 ()
{
int *p=(int *)calloc(1,sizeof(int));
if(p != NULL) //防止多次释放
{
free(p);
p=NULL;
}
if(p != NULL)
{
free(p);
p=NULL;
}
}