C语言动态内存管理malloc/calloc/realloc/柔性数组
介绍三个库函数,它们可以直接向内存申请特定大小的空间,然后就可以使用这些空间了。
这三个库函数分别是malloc? calloc? realloc
明明已经有结构体、数组、int、float、double等类型可以直接创建,向内存申请空间。为什么还要这三个库函数呢?
前者申请创建的内存大小是不能改变的,创建时是多少就是多少。而malloc、calloc和realloc申请的内存空间是可以改变的。如果感觉内存不合适,随时可以再加或者减。
前者创建的内存是在栈区,而通过malloc等函数申请的空间在堆区。用完之后还要通过free函数释放申请的空间。
malloc
void * malloc( size_t size);
以上是函数声明,malloc的返回类型是void *的指针,传的参数size表示想申请的内存大小,单位是字节。如果申请的内存太大超过栈区空间申请失败,则返回空指针。需要注意的是,在使用申请内存空间的时候,会用到这个返回的指针(解引用操作来赋值),如果返回的是空指针(申请失败),则导致程序崩溃。所以在使用的时候要检验一下,如果程序不为空指针再使用。
free
free(void * ptr)
free主要用于释放malloc、calloc和realloc申请的内存。free的参数是指针,这个指针必须是所申请存的初始地址。(如果不是,程序会崩溃)
int *p = (int *)malloc(40);
if (NULL != p)
{
for(int i = 0; i < 10; i++)
{
*(p+i) = i;
}
}
free(p);
p = NULL;
释放完申请的内存之后,p中还存有之前的地址,但指向的内容已经不再是可以使用的了,为了不让他变成野指针,必须手动把p置为空指针。
如果不适用free函数进行释放内存空间,那么会导致内存泄漏。
free中的指针如果是空指针,也不做任何处理。
申请动态内存使用后一定要记得用free函数进行释放,并且只能通过free函数释放!
calloc
void * calloc (size_t num,size_t size)
calloc有两个参数,返回类型也是指针。它也可以用来申请内存大小,表示申请num个size大小的内存。它的作用和malloc相似。调用之后返回一个申请内存的起始位置的指针。这个指针也可能是空指针(内存申请失败)。
calloc在申请内存后,会把元素初始化为0,而malloc和realloc不会。
realloc
void * realloc(void *ptr,size_t size)
realloc用于调节malloc、calloc和realloc申请的内存空间的大小。
realloc有两个参数,第一个参数是需要调节的内存的起始地址,第二个参数是size,表示需要申请的新内存空间大小。单位也是字节。返回类型也是指针。
但一般不把这个指针直接返回给需要调节的起始地址。
int main()
{
int *p =(int*) malloc(p,40);
if( p != NULL)
{
for(int i = 0; i < 10; i++)
{
*(p+i) = i;
}
}
//内存不够了
int *ptr = (int*)realloc(p,80);
if(ptr != NULL)
{
p = ptr;
}
//...
free(p);
p = NULL;
return 0;
}
如果申请失败,那么返回的是空指针,直接把返回的ptr给p,会导致原有的p的40个字节都没了,数据丢失,所以要检验一下返回的ptr是否为空指针,不为空指针再给p。
用realloc申请内存空间有两种情况,一种是原来的内存空间往后扩张的空间足够,没有被占用。那么返回的地址ptr的地址就和p的地址相同。
第二种是p后面的内存不够再扩张40个字节了,已经被占用了。所以系统要在栈区找块别的完整的80个字节的空间,把原来已经申请的40个字节的数据拷贝放在新的空间开辟一块80个字节的内存。这个时候新的内存起始位置当然和p不一样了。所以要把返回的ptr赋值给p,让p找到新开辟的空间来使用。
使用完以后也要用free来释放内存,并把指针置为空指针。
柔性数组
柔性数组出现在结构体中
struct A
{
int a;
char b;
int arr[0];
}hehe;
结构体的最后一个数组成员就是柔性数组。柔性数组的大小是可以变化的。它的内存不计入结构体的内存大小。结构体中柔性数组前面至少要有一个成员。用malloc动态分配内存时,分配的内存应该大于结构体大小。比如想要申请10个整型的柔性数组,在用malloc分配时,参数用之前的结构体大小再加上10个整型的大小。
(strcut A*)p = (struct A*)malloc(sizeof(hehe)+10*sizeof(int));
for(int i = 0; i < 10; i++)
{
p->arr[i] = i;
}
free(p);
这样柔性数组成员arr相当于有了10个整型元素的连续空间。
如果不使用柔性数组,把数组换成一个指针arr,通过malloc也能分配一定的内存,但是使用柔性数组便于释放空间。它只需要释放一次就可以。而对于指针arr来说,用malloc和realloc分配几次就需要释放几次,操作有点麻烦,还可能出错。
第二,柔性数组是连续的内存空间,有利于减少内存碎片。(内存碎片:使用malloc申请新的内存空间,新申请的内存空间之中可能会产生一些空隙,这些空间未能被使用,就是被浪费掉的空间,也就是内存碎片。)
这些是用柔性数组的优点。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!