我们已知的开辟空间的方式有:
int c=10;//申请一个四个字节的空间
char arr[10]={0};//申请十个字节的空间
以上申请内存的特点是:
1.申请出的内存大小是固定的
2.在变量或数组声明时,所占用的内存空间是固定的,不能由具体的应用灵活调整大小
有时候,程序所需要的内存空间是无法确定的,需要在程序运行过程中才能得知,这时候,就要借助动态内存分配。
void* malloc(size_t size)
该函数向内存申请一块连续可用的空间,并返回一个指向该空间的指针。
1⃣️如果开辟成功,返回一个只想开辟好的空间的指针
2⃣️如果开辟失败,则返回NULL,因此要对malloc函数的返回值进行检查
3⃣️函数的返回值类型是void*(泛型指针),其返回值类型由使用者确定
4⃣️若参数size为0,该做法属于未定义的行为
申请来的空间只有通过该指针进行操作,其他程序对这块内存空间的访问都视为非法访问。
用法如下:
//申请了一个40个字节大小的连续空间
int* ptr=(int*)malloc(sizeof(int)*10)
void free(void* ptr)
在C语言中free函数用来释放动态分配的内存
用法如下:
//将上面ptr所指向的40个字节大小的连续空间释放
free(ptr)
所谓释放,就是将由内存申请来使用的空间再归还给内存,在其他程序需要申请内存时,ptr所指向的这块空间同样可以被申请走,此时的ptr指针的内容虽然没有改变,但是却指向了一块未申请使用的空间而成为野指针,因此在free掉内存空间后将ptr置为NULL是一个好习惯。
1⃣️free函数不可用来释放不是通过动态开辟的内存,如
int a=10;
int* p=&a;
free(p)//非法操作
以上操作中,由于变量a所在的内存空间是在栈上申请的,而p指向这块空间,因此在free想要释放这块内存空间时,这是未定义的。
2⃣️如果free传入了一个NULL指针,则函数相当于什么都不做。
free和malloc的声明都在stdlib.h或malloc.h中,在使用时要引用相应的头文件
void* calloc(size_t num,size_t size);
calloc函数向内存申请num个大小为size的空间,并把每个字节设置为0,并返回一个指向该连续空间的指针,若申请失败则返回NULL;
//向内存申请10个大小为4的(32位)连续空间
int* ptr=(int*)calloc(10,sizeof(int))
其与malloc的唯一区别就是在申请空间的同时将数据初始化为0.
所以如果我们需要对申请的内存进行初始化,则可以使用calloc,但需要注意的是,其只能初始化为0而不能为其他数字。
realloc函数的出现使动态开辟的空间更加灵活。
有时我们会发现申请的空间太小了,有时我们又会觉得申请的空间太大了需要调小,那么可以使用realloc函数。
void* reallc(void* ptr, size_t size)
realloc函数可以做到对动态开辟的内存的大小进行调整。
ptr是要调整的地址,size表示需要调整的新大小
1⃣️realloc函数在将原有空间调整到新大小的前提下,还会将原数据空间的数据搬移到新空间中。
2⃣️realloc申请新大小的内存有两种情况
int* ptr=(int*)malloc(100);
//ptr=(int*)realloc(ptr,1000);
//错误用法:因为如果申请失败,realloc返回NULL,原空间就找不到了因此无法释放而造成内存泄漏
int* p=(int*)realloc(ptr,1000);
if(NULL==p)
{
assert(0);
return;
}
ptr=p;
free(p);
不是所有动态申请的空间都在堆上,C语言中还有一个动态申请内存函数alloca,函数原型:
void* _cdecl alloca(size_t size);
size是申请分配内存的字节数,返回值为分配到的内存地址。其特点是: