动态内存函数介绍:malloc、calloc、realloc、alloca

一.为什么存在动态内存分配?

我们已知的开辟空间的方式有:

int c=10;//申请一个四个字节的空间
char arr[10]={0};//申请十个字节的空间

以上申请内存的特点是:
1.申请出的内存大小是固定的
2.在变量或数组声明时,所占用的内存空间是固定的,不能由具体的应用灵活调整大小
有时候,程序所需要的内存空间是无法确定的,需要在程序运行过程中才能得知,这时候,就要借助动态内存分配。

二.动态内存函数介绍

  • malloc和free
  • calloc
  • realloc

1.malloc和free

malloc函数原型:

void* malloc(size_t size)

该函数向内存申请一块连续可用的空间,并返回一个指向该空间的指针。
1⃣️如果开辟成功,返回一个只想开辟好的空间的指针
2⃣️如果开辟失败,则返回NULL,因此要对malloc函数的返回值进行检查
3⃣️函数的返回值类型是void*(泛型指针),其返回值类型由使用者确定
4⃣️若参数size为0,该做法属于未定义的行为
申请来的空间只有通过该指针进行操作,其他程序对这块内存空间的访问都视为非法访问。
用法如下:

//申请了一个40个字节大小的连续空间
int* ptr=(int*)malloc(sizeof(int)*10)

free函数原型

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中,在使用时要引用相应的头文件

2.calloc

函数原型

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而不能为其他数字。

3.realloc

realloc函数的出现使动态开辟的空间更加灵活。
有时我们会发现申请的空间太小了,有时我们又会觉得申请的空间太大了需要调小,那么可以使用realloc函数。

函数原型

void* reallc(void* ptr, size_t size)

realloc函数可以做到对动态开辟的内存的大小进行调整。
ptr是要调整的地址,size表示需要调整的新大小
1⃣️realloc函数在将原有空间调整到新大小的前提下,还会将原数据空间的数据搬移到新空间中。
2⃣️realloc申请新大小的内存有两种情况

  • 情况1:原有空间的之后有足够大的空间
  • 情况2:原有空间后空间不足
    情况1中,要扩展空间就在原有空间之后追加相应大小的空间,原有空间的数据不变,情况2中,原有空间之后没足够的空间,则扩展的方法是:在堆上另外找一块合适大小的连续的内存空间。这样,realloc函数返回的地址就是一个新空间的地址,在申请失败时同样会返回一个NULL指针,因此在使用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);

4. alloca

不是所有动态申请的空间都在堆上,C语言中还有一个动态申请内存函数alloca,函数原型:

void* _cdecl alloca(size_t size);

size是申请分配内存的字节数,返回值为分配到的内存地址。其特点是:

  • 其开辟的空间在栈上,当出了其作用域后会由系统自动释放内存,无须像malloc需要free手动释放空间。
  • 再者,其开辟的空间与calloc类似,会将空间内的数据初始化为0。
  • 可移植性很差,对平台和编译器的依赖性,不推荐使用。

你可能感兴趣的:(笔记,新手入门,数据存储,c语言,内存管理)