文章目录
一、为什么要动态内存分配
当我们在c语言中声明一个数组的时候,必须先要指定一个数组的大小,但是在实际中我们往往不能提前知道我们设置的数组的大小,例如,假设我们要统计一个班级所有学生的数据,但不同班级的学生数量可能不同,在这种情况下我们通常会声明一个较大的数组,从而保证它可以容纳可能出现的最多元素。
动态分配内存就避免了这个问题,在程序的运行中给需要保存的数据分配内存。
二、相关函数
以下的相关函数声明都在#include <stdlib.h>
的头文件中。
1. malloc函数
c函数库中提供了两个函数,malloc和free,分别用于执行动态内存分配和释放,这里一定要牢记,在c语言中谁申请谁释放,如果你在你的程序中使用malloc函数申请了某块空间,那么一定要在程序运行的最后进行释放。
两个函数的声明如下:
void* malloc(size_t size); // 传入你想要申请空间的大小
void free(void pointer); // 传入指向你想要释放的空间的指针
需要注意的是,malloc申请得到的是一块连续的内存。如果内存池中是空的,或者目前可用的内存不够的时候,malloc在申请空间时会返回一个NULL
指针,因此我们使用malloc申请的时候需要对其进行检查,确保我们申请分配内存的操作是成功的。
需注意malloc的申请的内存必须进行手动的初始化。
2. calloc函数
函数声明如下:
void* calloc(size_t num_elements // 需要申请内存的元素个数
size_t element_size) // 需要申请的元素类型所占内存大小
calloc
函数也用于分配内存,但和malloc不同,calloc在返回指向内存的指针之前会把它们初始化为0,除此以外,我们也能从函数声明的传入参数中看出来,calloc根据传入的所需元素数量和每个元素字节数来计算最后总共需要分配的内存大小。
3. realloc函数
void realloc(void *ptr, // 指向原来内存的指针
size_t new_size) // 目前需要分配的内存大小
realloc函数用于修改一个原先已经分配的内存块的大小,如果扩大这个内存块,那么这块内存中原先的内容依然保存,新增加的内存添加到原先内存块的后面,新分配的内存不进行初始化;如果缩小一个内存块,该内存块的尾部内存会被拿掉,剩余部分依旧保留。若原先的内存块无法改变大小,则realloc会重新分配一块正确的内存,并把原先那块内存的内容复制到新块上。
三、代码举例
实现一个函数功能为: 创建一个长度为n的数组,其中存放任意小于n的数值,将其返回到主函数并进行输出。
代码如下:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int* create_random_array(int n){ // 生成一个随机数的数组
srand(time(NULL));
int *arr = malloc(n*sizeof(int));
for(int i=0; i<n; ++i){
arr[i] = rand()%n;
}
return arr;
}
void print_array(int* arr, int n){// 打印数组
for(int i=0; i<n; i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main(){
int n;
scanf("%d", &n);
int* arr = create_random_array(n);
printf("malloc => arr: ");
print_array(arr, n);
int* arr2 = calloc(n, sizeof(int));
printf("calloc => arr2: ");
print_array(arr2, n);
arr = realloc(arr, 2*n*sizeof(int));
for(int i=n; i<2*n; ++i){
arr[i] = 0;
}
printf("realloc => arr: ");
print_array(arr, 2*n);
free(arr);
free(arr2);
arr = NULL;
arr2 = NULL;
}
运行结果为:
四、错误使用动态分配内存警告的总结
- 不检查从malloc函数返回的指针是否是` NULL``;
- 访问动态分配的内存之外的区域;
- 向free函数传递一个并非由malloc函数返回的指针
- 在动态内存被释放后依旧访问它。
注:
分配内存在使用结束后不释放就会引起内存泄露。若我们在动态申请内存之后,由于没有及时释放,使得内存池中的可用空间越来越少,最终一无所有,使得程序无法执行下去。