调用动态内存分配的函数前需要先引入malloc.h
库
malloc 全称是memory allocation
,malloc
函数可以在动态储存区的堆内存中分配一块指定大小的连续内存空间,调用该函数时传入需要分配的字节数,如果分配成功将返回一个指向新分配内存的指针,如果分配失败返回NULL
1 void * malloc (size_t size) ;
如下代码在堆空间中分配了一块内存,并通过内存指针给该内存空间赋值;malloc
在某些情况下会发生内存分配失败的情况,如内存大小不足、内存碎片化严重,所以通过int_pointer != NULL
判断是否分配成功;在动态分配的内存使用完毕后,通过free
函数释放内存,动态分配的内存如果不释放会发生内存泄漏,释放后再把指向被释放的内存地址的指针 置空,避免该指针再次被程序调用,出现悬空指针问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int * int_pointer = (int *)malloc (sizeof (int ));if (int_pointer != NULL ) { (*int_pointer) = 10 ; printf ("value = %d\n" , (*int_pointer)); free (int_pointer); int_pointer = NULL ; } else { printf ("内存空间分配失败" ); }
通过malloc
在堆空间中创建了一个int
类型数组,该程序将输出连续的5
个堆空间中的内存地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #define ARR_LENGTH 5 int * arr_int_pointer = (int *)malloc (ARR_LENGTH * sizeof (int ));if (arr_int_pointer != NULL ) { for (int i = 0 ; i < ARR_LENGTH; i++) { printf ("*arr_int_pointer[%d] = %p\n" , i, &arr_int_pointer[i]); } free (arr_int_pointer); arr_int_pointer = NULL ; } else { printf ("内存分配失败" ); }
通过malloc
同样也能创建一个结构体指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 struct Data { int int_data; float float_data; }; struct Data * data_pointer = (struct Data*)malloc (sizeof (struct Data));if (data_pointer != NULL ) { data_pointer->int_data = 10 ; data_pointer->float_data = 22.2f ; printf ("int_data = %d, float_data = %.2f\n" , data_pointer->int_data, data_pointer->float_data); free (data_pointer); data_pointer = NULL ; } else { printf ("内存分配失败" ); }
calloc 全称是contiguous alloc
,calloc
函数可以在动态储存区的堆内存中分配一块连续的内存空间,空间的大小由函数的两个参数决定,分别可以理解为:代表元素数量和代表单个元素占用内存大小,调用该函数时传入这两个参数,如果分配成功将返回一个指向新分配内存的指针,并将该内存空间的每个字节初始化为零,如果分配失败返回NULL
1 void *calloc (size_t num_elements, size_t element_size) ;
其实这个函数满操蛋的,因为完全可以用malloc
来替代,如下,没有什么本质上的区别,只不过calloc
分配的内存空间把每个字节都初始化为零
1 2 int * arr_int_pointer1 = (int *)calloc (ARR_LENGTH, sizeof (int ));int * arr_int_pointer2 = (int *)malloc (ARR_LENGTH * sizeof (int ));
realloc 用于更改由malloc
或calloc
分配的内存块的大小,该函数需要两个参数,其中第一个代表需要修改的内存块的指针,第二个代表新的内存块大小;如果重新分配成功,则释放原内存块,并返回一个指向重新分配内存块的指针,重新分配失败则返回NULL
,原内存块仍然有效。
1 void *realloc (void *ptr, size_t new_size) ;
如果新的内存块大小,小于或等于原内存块的大小,那么原内存块可能被截断或保持不变,返回的指针可能与原地址相同,也可能是一个新的地址;如果新内存块的大小,大于原内存块的大小,那么原内存块的内容可能会被复制到新内存块中,并返回新的内存块的指针
1 2 3 4 5 6 7 8 #define ARR_LENGTH 5 int * pointer1 = (int *)malloc (ARR_LENGTH * sizeof (int ));int * pointer2 = (int *)realloc (pointer1, ARR_LENGTH * sizeof (int ));printf ("pointer1 = %p, pointer2 = %p\n" , pointer1, pointer2);
1 2 3 4 5 6 7 8 #define ARR_LENGTH 5 int * pointer1 = (int *)malloc (ARR_LENGTH * sizeof (int ));int * pointer2 = (int *)realloc (pointer1, (ARR_LENGTH + 1 ) * sizeof (int ));printf ("pointer1 = %p, pointer2 = %p\n" , pointer1, pointer2);
如果第一个参数指定的指针是NULL
,那么realloc
将分配一个新的内存块,类似于malloc
1 2 3 4 5 6 7 8 9 10 11 12 #define ARR_LENGTH 5 int * null_pointer = NULL ;int * new_arr_pointer = realloc (null_pointer, ARR_LENGTH * sizeof (int ));for (int i = 0 ; i < ARR_LENGTH; ++i) { new_arr_pointer[i] = i; printf ("pointer = %p\n" , &new_arr_pointer[i]); }