程序中需要动态分配一块内存时怎么办呢?我们可以定义一个缓冲区数组,但是这种方法不够灵活,C89要求定义的数组是固定长度的,而程序往往在运行时才知道要动态分配多大的内存,例如:
void foo(char *str, int n)
{
charbuf[?];
strncpy(buf,str, n);
......
}
n是由参数传进来的,事先不知道是多少,那么buf该定义多大呢?在第 1 节 “数组的基本操作”讲过C99引入VLA特性,可以定义charbuf[n+1] = {};,这样可确保buf是以'\0'结尾的。但即使用VLA仍然不够灵活,VLA是在栈上动态分配的,函数返回时就要释放,如果我们希望动态分配一块全局的内存空间,在各函数中都可以访问呢?由于全局数组无法定义成VLA,所以仍然不能满足要求。
进程有一个堆空间,C标准库函数malloc可以在堆空间动态分配内存,它的底层通过brk系统调用向操作系统申请内存。动态分配的内存用完之后可以用free释放,更准确地说是归还给malloc,这样下次调用malloc时这块内存可以再次被分配。
下面详细说明这两个函数的用法和工作原理。
#include <stdlib.h>
void *malloc(size_t size);
返回值:成功返回所分配内存空间的首地址,出错返回NULL
void free(void *ptr);
malloc的参数size表示要分配的字节数,如果分配失败(可能是由于系统内存耗尽)则返回NULL。由于malloc函数不知道用户拿到这块内存要存放什么类型的数据,所以返回通用指针void *,用户程序可以转换成其它类型的指针再访问这块内存。malloc函数保证它返回的指针所指向的地址满足系统的对齐要求,例如在32位平台上返回的指针一定对齐到4字节边界,以保证用户程序把它转换成任何类型的指针都能用。
动态分配的内存用完之后可以用free释放掉,传给free的参数正是先前malloc返回的内存块首地址。