4.动态内存管理

动态内存管理必要性

我们先看一下程序栈空间申请的数组的空间有什么特点?

  • 编译期间1就已经确定并分配了所要开辟的内存大小
  • 不需要程序员手动的去管理和维护连续的空间(比如数组)

正是需要在程序运行期间,动态的开辟调整和维护管理内存空间的需求才导致动态内存管理的必要性,动态申请的空间是在堆空间上的2


动态内存管理的相关函数

malloc
free
calloc
realloc

malloc

Required Header:<stdlib.h> and <malloc.h>

函数原型:void *malloc( size_t size );

malloc用于开辟size个字节的连续的内存空间。返回值:开辟成功后返回void*类型的指针,开辟失败返回NULL;参数size的意义是开辟连续的空间的总字节大小。3

举个例子:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main() {
    
    
    int* arr_int = (int*)malloc(sizeof(int) * 3);
    assert(arr_int);
    for (int i = 0; i < 3; ++i)
        arr_int[i] = 996+i;
    for (int i = 0; i < 3; ++i)
        printf("%d ", arr_int[i]);
    printf("\n");
    return 0;
}

以上代码在堆上开辟了三个连续整形大小的空间,assert断言一下arr_int,是为了防止空指针引用


free

Required Header:<stdlib.h> and <malloc.h>

函数原型:void free( void *memblock );

free函数用于释放申请的堆空间。free函数没有返回值;参数为要释放的连续空间的首地址。4

上面展示malloc功能的代码知道程序退出都没有对已经申请的堆空间进行释放,对动态内存的管理申请和释放需要成对出现才不会导致内存泄露

举个例子:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main() {
    
    
    int* arr_int = (int*)malloc(sizeof(int) * 3);
    assert(arr_int);
    for (int i = 0; i < 3; ++i)
        arr_int[i] = 996+i;
    for (int i = 0; i < 3; ++i)
        printf("%d ", arr_int[i]);
    printf("\n");
    free(arr_int);
    return 0;
}

在程序结束之前就进行对申请的堆空间释放

free(arr_int);

calloc

Required Header:<stdlib.h> and <malloc.h>

函数原型:void *calloc( size_t num, size_t size );

calloc函数用于申请初始化为0的堆空间。返回值是void*类型,是申请的连续空间的首地址;第一个参数num是元素的个数,第二个参数size是一个元素的大小。5

举个例子:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main() {
    
    
    int* arr_int = (int*)calloc(3, sizeof(int));
    for (int i = 0; i < 3; ++i)
        printf("%d ", arr_int[i]);
    printf("\n");
    return 0;
}

以上代码申请的三个整形大小的内存空间每个元素的初始值都是0


realloc

Required Header:<stdlib.h> and <malloc.h>

函数原型:void *realloc( void *memblock, size_t size );

realloc适用于调整已申请的内存空间大小。返回值是调整之后的内存空间地址;参数memblock是要调整的内存空间首地址类型void*,参数size是将要调整之后的内存空间字节大小。6

举个例子:

//输入提示:输入多个数字以空格隔开,回车结束输入
#include <stdio.h>
int main() {
    
    
    int num = 0;
    int size = 0;
    int* space = (int*)malloc(sizeof(int) * size);
    //动态管理空间获取输入
    while (scanf("%d", &num)) {
    
    
        size++;
        int* tmp = NULL;
        while ((tmp = (int*)realloc((void*)space, sizeof(int) * size)) == NULL);
        space = tmp;
        space[size - 1] = num;
        if (getchar() != '\n')
            continue;
        else
            break;
    }
    //遍历
    for (int i = 0; i < size; ++i)
        printf("%d ", space[i]);
    printf("\n");
    free(space);
    return 0;
}

以上代码实现了无穷大小的数组输入的功能实现,只要电脑物理内存足够,程序就一直可以动态调整堆空间大小不断接收新的输入并插入,需要注意的是,调整之后的内存空间还会将调整之前的数据移动到新空间,并且旧空间的内存不用手动去释放


  1. C语言编译过程 ↩︎

  2. 对程序内存逻辑空间不清楚的可以参考:C内存区划分 ↩︎

  3. 对于参数的解释原英文:Parameter:size is the bytes to allocate ↩︎

  4. 对于参数的解释原英文:Parameter:memblock is the previously allocated memory block to be freed
    ↩︎

  5. 对于参数的解释原英文:Parameters:num is the number of elements,size is the length in bytes of each element ↩︎

  6. 对于参数的解释原英文:Parameters:memblock is the pointer to previously allocated memory block,size is the new size in bytes ↩︎

猜你喜欢

转载自blog.csdn.net/qq_43808700/article/details/112719433