C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

 更新时间:2022年05月10日 09:01:05   作者:lonely-hermit  
C语言内存管理相关的函数主要有realloc、calloc、malloc、free等,下面这篇文章主要给大家介绍了关于C语言内存管理realloc、calloc、malloc、free函数的相关资料,需要的朋友可以参考下

C语言内存管理

malloc && realloc && free && calloc

c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理。

我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组

int nums[100];

上面这段代码是完全可行的,但是我们现在在不知道想要申请多少空间的情况下呢?比如说下面这个例子

int func(int n){
	int nums[n];
}

我们发现出错了,连编译都过不了,为什么呢?因为这段空间是编译过程中确定的,我们不能在程序运行过程中申请一段不确定大小的空间。

所以我初学的时候就解决不了这个问题,我采取了一个笨办法,就是申请一个足够大的空间,反正用不完,我内存大咋滴了,也不是不可以,这个方法确实解决了我当初的问题不是嘛,但是现在我们有更好的办法,就是动态的空间申请。

一、动态空间申请

// 函数原型
void *malloc(unsigned int num);

在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。

int func(int n){
    int *nums = (int *)malloc(sizeof(int)*n);
    return 0;
}

这样我们就解决了不能进行动态的申请内存的问题了,我不知道有没有读者注意到malloc函数的返回类型是空指针类型,这样的话就需要我们进行强制类型转换,我们在上面的函数中是将其转换为了int指针类型,这样的话我们指向的空间就可以存放int值,也就是说我们申请了一个大小为n的int数组。返回空指针在一定程度上实现了泛型。我们也可以对这个数组进行初始化。

int func(int n){
    int *nums = (int *)malloc(sizeof(int)*n);
    memset(nums,0,sizeof(int)*n);
    return 0;
}

如果说malloc是没有初始化的内存申请,那么calloc就带初始化的内存申请

// 函数原型
void* calloc(unsigned int num,unsigned int size);

原本两步的工作现在一步就完成了

int func(int n){
    int *nums = (int *)calloc(n,sizeof(int));
    return 0;
}

这里还有一个问题就是,这个空间不够用了怎么办,比如我们用数组实现栈,或者是队列,我们不能说一直动态的申请,或者不够了就加,实际上像python的list,他们在申请空间的时候都是多申请了一部分的,否则一会就加,一会就减,会影响效率,毕竟申请内存是需要向系统“打报告”的。

二、动态空间的扩容

我们之前申请的空间不够用了就需要扩容,我们可以用这个函数

// 函数原型
void *realloc(void *address,unsigned int newsize);

该函数重新分配内存,把内存扩展到 newsize。这里是扩展到多大,而不是扩展多少

int func(int n){
    int *nums = (int *)calloc(n,sizeof(int));
    nums = (int *)realloc(nums, sizeof(int)*n*2);
    return 0;
}

三、释放内存

当我们用完了这块动态内存空间时,我们需要手动释放,因为c没有智能的内存管理,只能依靠程序员自觉

// 函数原型
void free(void *address);

该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。

int func(int n){
    int *nums = (int *)calloc(n,sizeof(int));
    nums = (int *)realloc(nums, sizeof(int)*n);
    free(nums);
    return 0;
}

这里我们需要注意两件事,第一件事,动态分配的内存必须释放,否则就会内存泄露,第二件事,结构体指针需要递归释放,务必释放干净

typedef struct Node {
    int val;
    struct Node *next;
} Node;
void freeNode(struct Node *head){
    while(head){
        struct Node* temp=head->next;
        free(head);
        head = temp;
    }
}

更新一点知识,VLA变长数组,其实这么写在GCC中也是可以通过的

int n=10;
int nums[n];

我一开始看到这些代码也是很疑惑的,C语言到底支持不支持VLA变长数组啊,查了一点资料。

C90标准中并不支持VLA,C99开始支持VLA,很大的一个原因:FORTRAN中支持这种写法。C99中对对VLA有一些限制,比如变长数组必须是自动存储类型,也就是说,如果我上面两句放在函数外面就就不能通过编译了,这是因为在函数外面定义的是全局变量,此外,使用VLA不能对数组进行初始化,因为它的长度在运行时才能确定。

此外VLA并不是真正的变长,它实际上只是将数组的长度推迟到运行时确定而已,也就是说C90标准中,数组的长度必须在编译时期就知道,但C99支持VLA后,数组的长度可以推迟到运行时知道,但是,一旦长度确定,数组的长度就不能变了。

另外我在VC中编译并不能通过,在Clion中也不行,但是我leetcode中提交的时候可以通过,也就是gcc其实是支持的。

我并不建议这么写,还是老老实实的malloc吧。

到此这篇关于C语言详细分析讲解内存管理malloc realloc free calloc函数的使用的文章就介绍到这了,更多相关C语言内存管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 全局变量与局部变量在内存中的区别详细解析

    全局变量与局部变量在内存中的区别详细解析

    以下是对全局变量与局部变量在内存中的区别进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C语言二分法求解方程根的两种方法

    C语言二分法求解方程根的两种方法

    这篇文章主要为大家详细介绍了C语言二分法求解方程根的两种方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • C语言文件操作函数freopen详细解析

    C语言文件操作函数freopen详细解析

    替换一个流,或者说重新分配文件指针,实现重定向。如果stream流已经打开,则先关闭该流。如果该流已经定向,则freopen将会清除该定向。此函数一般用于将一个指定的文件打开一个预定义的流:标准输入、标准输出或者标准出错
    2013-10-10
  • 详解C语言和Python中的线程混用

    详解C语言和Python中的线程混用

    这篇文章主要介绍了C和Python中的线程混用的相关资料,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • C++实现动态规划过程详解

    C++实现动态规划过程详解

    动态规划是解决一类最优问题的常用方法,它是解决最优化问题的一种途径,在本文中,我们将讨论如何使用C++实现动态规划算法,并提供一些示例来帮助您更好地理解该算法
    2023-05-05
  • C语言深入讲解函数参数的使用

    C语言深入讲解函数参数的使用

    函数的参数分为形参和实参两种。形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用
    2022-04-04
  • FFmpeg实战之利用ffplay实现自定义输入流播放

    FFmpeg实战之利用ffplay实现自定义输入流播放

    ffplay是FFmpeg提供的一个极为简单的音视频媒体播放器,可以用于音视频播放、可视化分析。本文将利用ffplay实现自定义输入流播放,需要的可以参考一下
    2022-12-12
  • 深入HRESULT与Windows Error Codes的区别详解

    深入HRESULT与Windows Error Codes的区别详解

    本篇文章是对HRESULT与Windows Error Codes的区别进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 用C语言实现简单版9*9扫雷小游戏

    用C语言实现简单版9*9扫雷小游戏

    这篇文章主要介绍了用C语言实现简单版9*9扫雷小游戏,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • C语言辗转相除法求2个数的最小公约数

    C语言辗转相除法求2个数的最小公约数

    辗转相除法最大的用途就是用来求两个数的最大公约数。下面通过本文给大家介绍C语言辗转相除法求2个数的最小公约数,非常不错,感兴趣的朋友一起看看吧
    2016-12-12

最新评论