c语言-实现动态内存管理的库函数

文章目录

  • 前言
  • 一、什么是动态内存分配?
  • 二、malloc()和free()
    • 2.1 malloc()介绍
    • 2.2 malloc()的使用
    • 2.3 free()介绍
  • 三、calloc()
    • 3.1 calloc()介绍
    • 3.2 calloc()使用
  • 四、realloc()
    • 4.1 realloc()介绍
    • 4.2 realloc()使用
  • 总结


前言

本篇文章介绍c语言中实现动态内存管理的库函数,比如malloc()、free()、calloc()、realloc()

一、什么是动态内存分配?

在一般情况下,通过以下方式开辟内存空间

	int var = 20;  //在栈空间开辟4个字节的char str[10] = {0}; //在栈空间开辟10个字节连续的空间

上面开辟空间的方式有两个特点:

  1. 开辟空间的大小是固定的,不可变的
  2. 在栈中开辟,并且在编译时分配空间

当需要在程序运行过程中才能知道所有空间的大小时,这时候就需要动态内存分配。
动态内存分配是指在程序运行过程中,可以动态地向操作系统申请内存空间。
在c语言中,可以借助malloc()、free()、calloc()、realloc()这几个库函数实现动态内存的管理。
在这里插入图片描述


二、malloc()和free()

2.1 malloc()介绍

下面是cplusplus网站关于malloc()函数的介绍,如下:
在这里插入图片描述
作用:申请size个字节内存空间
说明:

  • 申请size个字节的空间
  • 分配的内存空间是没有经过初始化的,存储的是不定值

返回值说明:

  1. 如果传入的参数size为0,返回值为的标准未定义,由实现的编译器决定。
  2. 如果申请成功,返回这块内存空间的起始位置的指针,类型为void*,可以通过强制类型转换为期望解引用的类型
  3. 如果申请失败,返回一个空指针NULL

2.2 malloc()的使用

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
int main()
{//申请40个字节int* p = (int*)malloc(40);//判断申请是否成功if (NULL == p){printf("%s", strerror(errno));return 1;}//使用空间int i = 0;int sz = 40 / sizeof(int);for (i = 0; i < sz; i++){*(p + i) = i;}//打印for (i = 0; i < sz; i++){printf("%d ", *(p + i));}//使用完之后,释放空间free(p);p = NULL;return 0;
}

2.3 free()介绍

下面是cplusplus网站关于free()函数的介绍,如下:
在这里插入图片描述
作用:释放通过malloc()、calloc()、realloc()函数申请的空间
说明:

  • 如果ptr不是指向由malloc()、calloc()、realloc()申请的空间,那么释放时会引起未定义
  • 如果ptr为空指针,那么这个函数什么也不做。
  • 释放ptr指向的空间时,ptr本身的值不会被改变,即ptr依然会指向被释放的空间。所以,在释放ptr指向的空间后,应将ptr置为空指针。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
int main()
{//申请40个字节int* p = (int*)malloc(40);//判断申请是否成功if (NULL == p){printf("%s", strerror(errno));return 1;}//使用空间int i = 0;int sz = 40 / sizeof(int);for (i = 0; i < sz; i++){*(p + i) = i;}//使用完之后,释放空间free(p);p = NULL;return 0;
}

通过vs的内存监视查看(未释放前)
在这里插入图片描述
利用free()释放p指向的空间后
在这里插入图片描述
通过结果得出,free(p)释放p指向的空间后,p的指向没有改变,为了避免越界访问,因此可以将p = NULL

三、calloc()

3.1 calloc()介绍

下面是cplusplus网站关于calloc()函数的介绍,如下:
在这里插入图片描述
作用:申请一块num个size字节大小的连续空间。
说明:

  • 与malloc()不同之处的是,calloc()会在申请成功后,将每个字节初始化为0
  • 如果传入的参数size为0,返回值为的标准未定义,由实现的编译器决定,且返回值不可解引用。
  • 如果申请成功,返回这块内存空间的起始位置的指针,类型为void*,可以通过强制类型转换为期望解引用的类型
  • 如果申请失败,返回一个空指针NULL

3.2 calloc()使用

申请10个int大小的空间(10*sizeof(int)个字节)

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
//申请10个int的空间
int main()
{int* p = (int*)calloc(10, sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return 1;}//释放空间free(p);p = NULL;return 0;
}

通过vs的内存监视查看
在这里插入图片描述
calloc()申请成功后,将每个字节初始化为了0,也可利用malloc()+memset()实现。

四、realloc()

4.1 realloc()介绍

下面是cplusplus网站关于realloc()函数的介绍,如下:
在这里插入图片描述

作用:将ptr指向的内存块的大小改变为size个字节大小
说明:

  • 如果ptr是一个空指针,那么realloc()的作用与malloc()一样,都是申请size个字节大小的连续内存
  • realloc()申请内存时,申请得到的内存分为两种情况(扩容:申请大于ptr指向的内存大小
    假设ptr指向的内存块大小为40个字节,现扩容到80个字节:
  1. 在ptr指向的内存块后面直接扩容
    在这里插入图片描述

  2. 开辟一块大小为size的新空间
    在这里插入图片描述
    在这种情况下,在扩容成功后,会将原始内存的内容拷贝到扩容内存中,然后释放原始内存。

4.2 realloc()使用

  1. 传入空指针
    在这里插入图片描述
  2. 扩容
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int main()
{//申请10个int的空间int* p = (int*)malloc(10*sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return 1;}memset(p, 0, 40);//扩容将p指向的内存块扩容到80个字节int* pp = (int*)realloc(p, 80);if (pp != NULL){p = pp;pp = NULL;}//释放pfree(p);p = NULL;return 0;
}

通过vs的内存监视查看内存情况
在这里插入图片描述
p和pp指向的空间不相同,说明此次扩容是在新的内存上开辟;同时,pp的前40个字节的内容和p的40个字节的内容是相同的,说明新扩容的内存将原始内存的内容进行了拷贝。


总结

本篇文章介绍了在c语言中实现动态内存管理的四个库函数,malloc()、free()、calloc()、realloc()。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/422923.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python从入门到进阶】47、Scrapy Shell的了解与应用

接上篇《46、58同城Scrapy项目案例介绍》 上一篇我们学习了58同城的Scrapy项目案例&#xff0c;并结合实际再次了项目结构以及代码逻辑的用法。本篇我们来学习Scrapy的一个终端命令行工具Scrapy Shell&#xff0c;并了解它是如何帮助我们更好的调试爬虫程序的。 一、Scrapy Sh…

MyBatis关联查询实战:一对一与一对多详细解析

MyBatis关联查询实战&#xff1a;一对一与一对多详细解析 MyBatis是一款强大的持久层框架&#xff0c;提供了多种方式来处理关联查询&#xff0c;其中包括一对一和一对多的情况。在本文中&#xff0c;我们将深入探讨这两种关联查询的实现方式&#xff0c;并通过具体的示例代码进…

poi-tl模板引擎根据树形结构输出word文档(文档模板)

最近在做一个需求&#xff0c;就是根据当前的树形结构&#xff0c;输出到word文档中。下面展示一下小demo 目录 1、输入&#xff1a; 2、输出&#xff1a;文档.docx 3、代码展示 4、测试结果 4.1、模板文档内容 4.2、输出文档 5、总结 1、输入&#xff1a; root---树节…

Unity New Input System 及其系统结构和源码浅析【Unity学习笔记·第十二】

转载请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/132534422 作者&#xff1a;CSDN|Ringleader| 主要参考&#xff1a; 官方文档&#xff1a;Unity官方Input System手册与API官方测试用例&#xff1a;Unity-Technologies/InputS…

Aria2 WebUI控制台 任意文件读取漏洞复现(CVE-2023-39141)

0x01 产品简介 Aria2 WebUI控制台是用于下载文件的实用程序。它支持 HTTP(S)/FTP/SFTP/BitTorrent 和 Metalink 协议。aria2可以从多个来源/协议下载文件,并尝试利用您的最大下载带宽。它支持同时从HTTP(S)/FTP/SFTP和BitTorrent下载文件,而从HTTP(S)/FTP/SFTP下载的数据上…

算法之【前缀和】讲解

前言&#xff1a; 我们首先要明白何前缀和&#xff1f; 前缀和就是快速求出数组中某一个连续区间的和。算法的时间复杂度会将一个等级&#xff01; 本文章主要讲解前缀和模板&#xff0c;分别为一维前缀和和二维前缀和。 一维前缀和&#xff1a; 第一步&#xff1a;预处理…

Vue+ElementUI渲染select下拉框

User.java /*实现getter和setter方法注解*/ Data public class User {private Integer id;private String name; } UserMapper.java Mapper public interface CommonUserMapper {/**查询所有*/List<CommonUser> selectAllCommonUser(); } UserMapper.xml <?xml …

makefile 编译动态链接库使用(.so库文件)

makefile 编译动态链接库使用&#xff08;.so库文件&#xff09; 动态链接库:不会把代码编译到二进制文件中&#xff0c;而是在运行时才去加载&#xff0c; 好处是程序可以和库文件分离&#xff0c;可以分别发版&#xff0c;然后库文件可以被多处共享 动态链接库 动态&#…

支付宝:多线程事务怎么回滚?说用 @Transactional 可以回去等通知了!

1&#xff0c;最近有一个大数据量插入的操作入库的业务场景&#xff0c;需要先做一些其他修改操作&#xff0c;然后在执行插入操作&#xff0c;由于插入数据可能会很多&#xff0c;用到多线程去拆分数据并行处理来提高响应时间&#xff0c;如果有一个线程执行失败&#xff0c;则…

2011-2022年全国各地级市互联网普及率/互联网宽带接入用户数数据

2011-2022年全国各地级市互联网宽带接入用户数/互联网普及率数据 1、时间&#xff1a;2011-2022年 2、范围&#xff1a;包括295个地级市 3、指标&#xff1a;行政区划代码、年份、地区、互联网宽带接入用户_千户、常住人口数_千人、户籍人口数_千人、每百人互联网宽带用户_常…

续签KES证书

MiniO KES&#xff08;密钥加密服务&#xff09;是 MinIO 开发的一项服务&#xff0c;旨在弥合在 Kubernetes 中运行的应用程序与集中式密钥管理服务 &#xff08;KMS&#xff09; 之间的差距。中央 KMS 服务器包含所有状态信息&#xff0c;而 KES 在需要执行与获取新密钥或更新…

docker运行redis,jdk,nginx

Redis 1.查询redis [rootlocalhost ~]# docker search redis NAME DESCRIPTION STARS OFFICIAL redis Redis is an open source key-value store that… 12620 …