C语言中,动态内存分配(使用malloc和free函数)虽然方便,但是会存在不少开销。为了避免这些开销,可以通过一些技巧进行优化。
1. 内存池
内存池的机制是,事先申请一块固定大小的内存,并将其分成若干个固定大小的块。在需要动态分配内存时,直接从内存池中取出一个空闲块,使用完后将其放回池中。由于内存池中所有块大小固定,申请和释放时只需要维护一个索引,且不使用malloc和free函数,因此可以避免内存分配和释放所产生的开销。
以下是一个内存池的示例代码:
#include <stdio.h>
#include <stdlib.h>
#define BLOCK_SIZE 10
#define POOL_SIZE 50
char pool[POOL_SIZE];
char* pool_alloc() {
static int idx = 0;
if (idx + BLOCK_SIZE > POOL_SIZE) {
return NULL;
}
char* ptr = &pool[idx];
idx += BLOCK_SIZE;
return ptr;
}
int main() {
char* ptrs[5];
for (int i = 0; i < 5; i++) {
ptrs[i] = pool_alloc();
}
for (int i = 0; i < 5; i++) {
printf("%p\n", ptrs[i]);
}
return 0;
}
在这个代码中,我们首先定义了一个50字节大小的内存池(使用char类型是为了方便计算偏移),每次从池中取出大小为10字节的块。在主函数中我们申请了5个块,并将它们的地址打印出来。
2. 预先分配数组
另一种避免使用malloc和free函数的方法是,预先分配一个由多个元素组成的数组,使用时直接从数组中取出空闲的元素即可。这种方法可以减少内存分配的开销,但是需要在初始化时将数组分配好,因此必须提前知道需要的数组大小。
以下是一个使用数组预分配的示例代码:
#include <stdio.h>
#include <stdlib.h>
#define MAX_OBJECTS 1024
int free_objects[MAX_OBJECTS];
int next = 0;
int get_free_object() {
if (next >= MAX_OBJECTS) {
return -1;
}
int obj = free_objects[next];
next++;
return obj;
}
void free_object(int obj) {
next--;
free_objects[next] = obj;
}
int main() {
int* ptrs[5];
for (int i = 0; i < 5; i++) {
int idx = get_free_object();
if (idx == -1) {
ptrs[i] = NULL;
break;
}
ptrs[i] = &free_objects[idx];
}
for (int i = 0; i < 5; i++) {
printf("%p\n", ptrs[i]);
}
return 0;
}
在这个代码中,我们预先定义了一个大小为1024的int类型数组,将它全部标记为空闲。在申请内存时,使用get_free_object函数取出下一个空闲元素的索引,如果没有空闲元素则返回-1。在使用完后,将元素的索引放回数组中。在主函数中我们申请了5个元素,并将它们的地址打印出来。