前言:
首先,让我们来回顾一下一些常见的内存开辟方式
int val = 20;//在栈空间上开辟了四个字节
char arr[10]={0};//在栈空间上开辟了10个字节的连续空间
上述开辟空间的方式有两个特点:
- 空间开辟大小是固定的
- 数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整
但是有时,我们需要的空间大小要在程序运行时才知道,那以上开辟空间的方式就无法满足我们的需求。因此,C语言引入了动态内存开辟,让程序员可以自己申请和释放空间。C语言中的动态内存管理是通过一组标准库函数实现的,接下来就让我们来一起学习吧~
1.malloc
该函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
void* malloc(size_t size);
- 使用时需包含头文件<stdlib.h>
- 函数返回值类型为void*,所以malloc函数并不知道开辟空间的类型,需要使用者自己决定。
- 若开辟成功,则返回一个指向开辟好空间的指针。
- 若开辟失败,则返回一个指针NULL,因此要检查malloc的返回值。
- 若参数size的值为0,则malloc的行为是标准未定义的,取决于编译器。
使用举例
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main ()
{
int i,n;
char * buffer;
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
for (n=0; n<i; n++)
buffer[n]=rand()%26+'a';
buffer[i]='\0';
printf ("Random string: %s\n",buffer);
free (buffer);
return 0;
}
2.free
free函数用于动态内存的释放与回收
void free(void* ptr);
- 若参数ptr是NULL指针,则函数什么事情都不做
- 若ptr指向的空间不是动态开辟的,那么free的行为是未定义的
使用举例
#include <stdlib.h> /* malloc, calloc, realloc, free */
int main ()
{
int * buffer1, * buffer2, * buffer3;
buffer1 = (int*) malloc (100*sizeof(int));
buffer2 = (int*) calloc (100,sizeof(int));//下面会讲到这个函数
buffer3 = (int*) realloc (buffer2,500*sizeof(int));//下面会讲到这个函数
free (buffer1);
free (buffer3);
return 0;
}
3.calloc
calloc也用于动态内存分配,为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。
void* calloc(size_t num,size_t size);
- 该函数与malloc的区别在于calloc会在返回地址之前把申请的每个字节初始化为0
使用举例
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int*)calloc(10,sizeof(int));
if(NULL!=p)
{
int i = 0;
for(i = 0;i<10;i++)
{
printf("%d",*(p+i));
}
}
free(p);
p=NULL;
return0;
}
//打印结果全为0
4.realloc
realloc可以做到对动态开辟内存大小的调整
void* realloc(void*ptr,size_t size);
- ptr是要调整的内存地址
- size为调整之后的大小
- 返回值为调整之后的内存起始位置
- realloc调整内存空间有两种情况
- 原有空间之后有足够的空间:此时扩展内存直接在原有内存之后进行追加,原来空间的数据不发生变化。
- 原有空间之后没有足够的空间:此时在堆上另找一个合适大小的连续空间来使用,函数返回一个新的内存地址。
- 调整空间失败,返回NULL
- realloc可以实现和malloc一样的功能
-
(int*)p =(int*)realloc(NULL,40);
realloc使用举例
#include <stdio.h>
#include <stdlib.h>
int main()
{
int*ptr = (int*)malloc(100);
if(ptr!= NULL)
{
//业务处理
}
else
{
return 1;
}
//进行扩容
int* p = NULL;
p = realloc(ptr,1000);
if(p != NULL)
{
ptr = p;
}
//业务处理
free(p);
return 0;
}
注意:上述代码中,不能把realloc的返回值直接赋值给ptr,因为如果realloc开辟空间失败返回空指针,这样的做法会导致原来空间的地址也找不到!
总结及注意点
1.malloc:分配所需大小的连续内存块,并返回指向该内存块起始位置的指针。
2. calloc:类似于malloc,但它还会初始化分配的内存为零。
3. realloc:调整之前使用malloc或者calloc分配得到的内存块大小。
4. free: 释放先前使用上述三个函数之一分配的动态内存。
- 动态申请到堆(heap)上面去了而非栈(stack),因此需要手动管理这部份记忆体资源。否则可能导致记忆体泄露(memory leak)等问题发生;
- 使用完毕后务必调用free()进行释放;
- 对null pointer调用free是安全无害操作;
- 在使用未经初始化过得pointer之前确保赋予权威性来源数据;
- 再次利用同一个pointer进行另外一次memory allocation请求前,请确认已经将其先前关联内容给解除(free)掉了。
好啦,以上就是关于c语言动态内存管理的介绍啦!防止下次迷路,点赞收藏加关注哦ovo