引言
为什么会有内存操作函数呢?我们已经可以用定义变量,数组的方式来从内存开辟一块空间,但是我们一旦这么做了以后,所开辟的空间就固定住了,例如:
int main()
{
int a = 0;
int arr[10] = { 0 };
return 0;
}
再之后我们如果想存更大的数组的时候,比如存20个整数,这个数组arr就不能满足我们的要求了,就需要创建新的数组才可以,这时候就可能造成空间的浪费。
为了避免这种情况的发生,我们有了动态内存管理,可以使我们自由申请调整释放空间,非常的灵活好用。
malloc函数
首先使用此函数需包含头文件stdlib.h,而且同下函数,都需要包含此头文件。
void* malloc( size_t size );
动态内存开辟函数malloc向内存申请一块连续可用的空间,并且返回这块空间的起始地址为void*类型指针;如果申请空间失败则返回NULL指针。
而如果你找茬的话,希望申请一块大小为0的空间,那就只能看你用的编译器的脾气了:>
free函数
void free( void* ptr );
free函数对ptr指针指向的动态开辟申请的空间进行释放和回收。
如果你给他的不是动态开辟的内存,那么这个行为是未定义的;
如果你给他的指针是NULL空指针的话,无事发生。
注意!当我们释放完毕空间后,如果有定义指向那块动态空间的指针就会变成野指针,需要及时置为空指针。
#include <stdlib.h>
int main()
{
int* ptr = (int*)malloc(20); //申请动态空间
if ( ptr == NULL )
{
perror("malloc"); //判断申请空间是否成功
return 1; //如果申请失败直接提前返回
}
//进行操作......
free(ptr); //此时ptr成为野指针,需及时置为空指针
ptr = NULL;
return 0;
}
calloc函数
void* calloc( size_t num, size_t size );
动态内存开辟函数calloc向内存申请num个大小为size的元素开辟空间,并将此块空间初始化为0.
如果开辟成功,返回开辟空间初始位置指针(void*) ;如果申请失败同malloc函数返回NULL。
其实calloc就是malloc函数的一个改进版,加入了细分的数量和单位大小,还添加了初始化步骤,其他与malloc函数几乎无异。
realloc函数
void* realloc( void* ptr, size_t size );
动态内存调整函数realloc是我们可以对动态开辟的内存进行大小的调整,具体为调整ptr指向的动态内存空间为size大小,返回值为调整后的内存起始位置指针。
这时候就有两种情况:1.原空间大于调整后的空间。2.原空间小于调整后的空间
第一种情况比较简单,因为是调小了空间,一定有足够的空间进行操作。
而第二种情况我们就需要分析,如果延展空间的话,原空间后面的空间是否能满足我们的要求呢。
原空间 | 尚未分配的空间 | 已经分配好的空间 |
① | ② | ③ |
如果是原内存后空间能够满足我们调整后空间大小要求的话,直接调整到需要的大小,然后返回原空间的初始位置的指针;
如果原内存后的空间不满足我们调整的要求的话,即尚未分配的空间②大小小于调整后空间与原空间的差值,这时候我们的realloc函数就会再找一块满足调整后大小的内存空间,然后把我们的原空间的内存复制一份到新空间去,并返回新位置初始位置的指针,释放原空间。
柔性数组
柔性数组的概念是针对于结构体来说的,我们结构体中最后一个成员如果是一个未定义大小的数组的话,这个成员就是一个柔性数组
struct st_type
{
int i;
int a[];//柔性数组成员
};
有几点需要注意:结构中的柔性数组成员前面必须至少⼀个其他成员;
sizeof 返回的这种结构大小不包括柔性数组的内存;
包含柔性数组成员的结构用malloc()函数进⾏内存的动态分配,并且分配的内存应该⼤于结构的大小,以适应柔性数组的预期大小。
#include <stdio.h>
#include <stdlib.h>
struct S
{
int i;
int arr[];
};
int main()
{
int sz = sizeof(struct S); //包含柔性数组的结构体大小
printf("%d\n", sz);
struct S* ptr = (struct S*)malloc(sz + 100 * sizeof(int)); //给结构体申请动态内存空间
ptr->i = 100;
for (int h = 0;h < ptr->i;h++)
{
ptr->arr[h] = h;
printf("%d ", ptr->arr[h]+1);
}
free(ptr);
ptr = NULL;
return 0;
}