1. malloc
直接创建数组一般存储在函数调用栈上,而使用 malloc 分配内存从而进行存储的数据则是存放在堆区;堆区的数据与函数调用栈上的数据不同,堆区数据在函数释放后也不会释放内存,需要用 free() 主动释放
#include <stdio.h>
#include <stdlib.h>
#define PLAYER_COUNT 10
int main(){
int *players = malloc(PLAYER_COUNT * sizeof(int));
for (int i = 0; i < PLAYER_COUNT; ++i) {
players[i] = i;
}
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d ", players[i]);
}
free(players); // 释放内存
return 0;
}
2. 函数参数应为二维指针
free() 释放后的内存块对存在其中的值无影响,还会保留在内存块中,所以在调用 malloc 时,需要对新来的内存块上的值进行初始化操作(初始化操作中的二维指针,实质上就是在函数内部修改外部的指针变量,看自己那篇18年的博客,有详解)
#include <stdio.h>
#include <stdlib.h>
#define PLAYER_COUNT 10
void InitPointer(int **ptr, int length, int default_value){
*ptr = malloc(length * sizeof(int));
for (int i = 0; i < length; ++i) {
(*ptr)[i] = default_value;
}
}
int main(){
// 和向函数传递想要修改的参数值的情况相同,必须将变量的地址传入函数才能进行修改,此处就是指针变量的地址传入InitPointer函数,进而修改指针变量的值
int *players;
InitPointer(&players, PLAYER_COUNT, 2);
for (int i = 0; i < PLAYER_COUNT * 2; ++i) {
printf("%d ", players[i]);
}
free(players);
return 0;
}
3. calloc
函数 calloc 与 malloc 不同,calloc 返回的内存会自动被清为 0,相当于做了一个预处理工作,不用自己做
players = calloc(PLAYER_COUNT, sizeof(int));
4. realloc
realloc 函数,对原先的内存(注意,是在原有的内存基础上进行分配的)进行重新分配并增加或减少部分内存(以旧换新的感觉),但注意,realloc 新加的内存不会做清空操作,里面的值不能确定
int *players;
InitPointer(&players, PLAYER_COUNT, 2);
// 函数 realloc 的用法
players = realloc(players, 4*sizeof(int)); // 重新分配四块内存
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d ", players[i]); // 2 2 2 2 -842150451 ... ,只能确定前四个值,后面的值无法确定,因为是在原有空间的基础上重新分配了四块内存
}
printf("\n");
players = realloc(players, PLAYER_COUNT * 2 * sizeof(int)); // 重新分配20块内存
for (int i = 0; i < PLAYER_COUNT * 2; ++i) {
printf("%d ", players[i]); // 2 2 2 2 -842150451 -842150451 -842150451 ... 后面一直都是 -842150451,这个数字是什么含义?
}
free(players);
5. 分配内存之后...
内存分配可能会失败,所以在使用 malloc calloc realloc 函数后,需要判断指针是否分配到了内存
if(players){
... // 指针指向的地方有内存才有意义
}else{
...
}
6. 注意事项
常见指针使用错误:
1)忘记在使用指针完毕后释放内存
2)使用了已经释放的内存(指针指向的内存被释放,但是指针变量并没有被销毁,还是可以继续使用的,如果在 free() 后再次使用该指针变量,就是这种情况,这种指针就是野指针)
3)使用了超出边界的内存(类似数组越界)
4)改变了内存的指针,导致无法正常释放(一个指针变量指向一块内存,如果这时将指针变量的值修改,使其指向其他内存,那原有的那块内存就会无法正常释放,因为没有指针变量指向它)
动态内存使用建议:
1)避免修改指向已分配内存的指针(对应 4)
2)对于 free() 后的指针主动置为 NULL(对应 2)
3)避免将过多的指针指向动态分配的内存(一旦其中一个指针使用 free() 操作,其他指针根本不知道,其他指针就化为了野指针)
4)动态内存遵从谁分配谁释放的原则