目录
前言
为什么要动态申请内存?我们知道函数的调用是C语言里非常常见的,有些函数调用时需要传递参数比如数组的地址,如果我们在函数里只用静态申请数组的话会使程序的可移植性降低,为了灵活使用函数,所以会用到动态申请。
例如:我们要写一个函数,函数的传参为numsSize,函数的功能是申请一个大小为numsSize大小的整形数组,这个numsSize并不是个常数,这时就必须用到动态申请了。
如何动态申请
错误示范:
int numsSize;
int arr[numsSize];
这样写的话编译器是不会让程序通过的,因为numsSize不是个常数。
这时就要用到动态申请的函数malloc了。该函数被包含在#include <stdlib.h>头文件里。用法如下
int *arr=malloc(Size);
其中Size是需要申请的空间大小,单位是字节,一般我们不这样写,我们一般写成:
int *arr=malloc(sizeof(int)*numsSize);
我们需要申请一个大小为numsSize的整形数组,所以数组的大小为sizeof(int)*numsSize,这样写直观明了。
内存释放——free
动态申请内存和一般申请相比不同点在于,静态申请的内存是放在栈区的,计算机内存里除了栈区还有堆区,堆区就是动态申请内存的存放地,栈区的特点是申请的内存不需要我们手动释放,一个变量的生命周期结束后系统会自动将其释放;而堆区需要我们手动释放,如果我们不手动释放,则有可能会造成内存泄漏等重大问题(内存泄漏是指一个程序在运行时所占用的内存不断增大,不及时处理会导致计算机内存占用过多)。
所以我们使用动态申请的内存结束后,一定要记等将其释放:
free(arr);
注意free释放空间只对动态申请的空间起用,不可以手动释放静态申请的空间,且对动态申请的空间只能手动释放一次,不可重复释放。
如何判断一个内存是否已经被释放
动态申请的空间被释放后,如果不将其置空,则其会变成一个野指针,所以我们可以养成一个习惯:每次free释放空间后再将其置空
free(arr);
arr = NULL;
要判断arr是否已经被释放,我们可以增加一个判断:
if(arr!=NULL){
free(arr);
arr = NULL;
}
所以针对以上的案例:申请一个大小为numsSize的数组,我们可以给出以下答案:
int main(){
int numsSize;
scanf("%d", &numsSize);
int *arr = malloc(sizeof(int)*numsSize);
free(arr);
return 0;
}
calloc函数
malloc函数是动态申请常见的函数,除此之外还有一些函数也能动态申请,但具体功能不同,比如calloc函数:
原型 void * calloc(size_t nmemb, size_t size);
size_t是无符号整形的定义,该函数的功能是在堆区中动态申请nmemb块,每块大小为size的内存,所以申请的空间总大小为nmemb*size。该函数使用后也需要手动释放内存。
relloc函数
原型 void* realloc(void* s, unsigned int newsize);
s是已经动态申请过了的空间地址,该函数的功能是对已经动态申请过的空间s重新申请一个大小为newsize的空间。如果原空间地址后面的空间足够多,则该函数直接在原空间进行扩容,如果不够,则开辟一个新空间,然后将原空间销毁,返回新空间地址。
以上便是对动态申请的简单了解。