我们已经掌握了一些开辟内存的方式,例如在栈空间开辟空间存储不同类型的数据。
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
类似这样的开辟方式,内存的大小是固定好的,数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。有些时候我们需要的空间大小在程序运行的时候才能知道,这样的话,那数组的编译时开辟空间的方式就不能满足了。所以需要动态开辟。
1.动态开辟函数
malloc 和 free
C语言提供了一个动态内存开辟的函数:
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。 如果开辟成功,则返回一个指向开辟好空间的指针。 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:
free函数用来释放动态开辟的内存。 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。 如果参数 ptr 是NULL指针,则函数什么事都不做。
注意:malloc和free的头文件是 stdlib.h 。
举例:
calloc
calloc函数也可以用来动态内存分配,与malloc的区别是calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
举例:
realloc
realloc函数可以对开辟的空间进行调整。
ptr 是要调整的内存地址,size是调整之后新大小。返回值为调整之后的内存起始位置。这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
那么开辟新空间就会出现两种情况:
情况1:原有空间后的空间足够
情况2:原有空间后空间不足
图解如下:
2.柔性数组
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员。
例如:
struct S
{
int a;
char c;
int arr[];//arr[0]也可以
}
柔性数组的特点:
结构中的柔性数组成员前面必须至少一个其他成员。sizeof 返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
使用:
柔性数组的好处:
方便内存释放这样有利于访问速度