声明数组时,必须指定数组长度,才可以编译,但是如果需要在运行时,指定数组的长度的话,那么就需要动态的分配内存。
C函数库stdlib.h提供了两个函数,malloc和free,分别用于执行动态内存分配和释放,这些函数维护一个可用的内存池,当程序需要内存时,它就调用malloc从内存池中提取一块合适的内存,并向该程序返回一个指向这块内存的指针,这块内存没有以任何方式进行初始化。如果需要初始化,可用使用calloc函数。当一块分配的内存不再使用时,程序应该调用free函数把它归还给内存池。
void *malloc(size_t size);
void free(void *pointer);
当malloc申请内存失败时,返回的是NULL指针,所以需要对malloc返回值进行检查,确保非NULL。而free的参数,要么是NULL,要么是malloc,calloc或者realloc返回的值。向free传入NULL,不会产生任何效果。
malloc返回的是void *类型的指针,所以有的编译器可能在使用之前,需要行类型转换。
char *sPtr;
//类型转换一下
sPtr = (char *)malloc(12);
strcpy(sPtr, "yangxunwu");
calloc,也是分配内存,不过在分配之前会把内存初始化为0,而malloc不会初始化
void *calloc(size_t num_elements, size_t element_size);
calloc还有一个区别是它的参数包含元素的个数,以及单个元素的字节数。
realloc用于修改一个原先以及分配内存块的大小,使用这个函数可以是一块内存扩大或者缩小,如果原先的大小可以改变,那么将直接在内存块进行操作,如果无法改变,那么realloc将重新分配正确大小的内存,并把原先的内存内容复制到新的块上。
void * realloc(void *ptr, size_t new_size);
在使用realloc后就不可以使用指向旧内存的指针,而是应该改用realloc所返回的指针。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *sPtr;
char *nPtr;
//类型转换一下
sPtr = malloc(12);
strcpy(sPtr, "yangxunwu");
printf("%s\n", sPtr);
//使用新的指向内存的指针
nPtr = realloc(sPtr, 20);
printf("%s\n", nPtr);
return 0;
}
如果realloc的第一个参数为空,那么就和malloc一样。
当内存分配使用后不需要使用时可以使用free函数释放内存到内存池中,如果malloc或者realloc或者calloc失败返回的是NULL,所以对NULL进行指针解引用会报错,或者返回指针后,操作超过了边界,free释放非动态分配的内存,或者部分动态分配的内存都是错误的。如果内存已经释放,在访问是错误的,或者只申请内存不释放,会导致内存泄露。