15. 《C语言》——【如何动态内存开辟】

在这里插入图片描述

亲爱的读者,大家好!我是一名正在学习编程的高校生。在这个博客里,我将和大家一起探讨编程技巧、分享实用工具,并交流学习心得。希望通过我的博客,你能学到有用的知识,提高自己的技能,成为一名优秀的程序员。如果你有任何疑问或建议,请随时在评论区留言,让我们一起成长进步!现在,让我们开始这场知识之旅吧!



🚀个人主页:FEN03
📚收入专栏:C语言

在这里插入图片描述



文章目录

  • 📚前言
  • 📘1. 为什么要动态内存分配❓
  • 📗2. 如何去动态内存开辟❓
    • 🔖2.1 malloc
    • 🔖2.2 free
    • 🔖2.3 calloc
    • 🔖2.4 realloc
  • 👋结束语


📚前言

为什么需要动态内存开辟,如何向内存申请空间?接下来,就让我们去探讨吧~


📘1. 为什么要动态内存分配❓


在先前,我们开辟内存的方法无非是在栈区创建一个变量,或者说一个数组。

#include<stdio.h>
int main()
{
	int a = 0; //在栈区开辟了4个字节的空间
	int arr[10] = { 0 }; //在栈区开辟了40个连续字节的空间
	return 0; 
}

这2种内存开辟,都存在着2种特点

  1. 内存开辟的大小是固定的了。
  2. 数组在创建时,必须是指定它的长度,一旦确定大小后不能再进行更改

为了迎合更高的要求,上述的情况就不能满足了。那么为了解决这一问题,C语言引入了动态内存开辟,这样程序员就可以灵活的去申请和释放空间。

那么接下来就让我们探索如何去动态的向内存开辟。


📗2. 如何去动态内存开辟❓

那么为了实现动态内存的开辟,C语言提供了4个函数,那么接下来,就让我们去学习如何使用这些函数吧~⬇️


🔖2.1 malloc

为了实现动态内存开辟,C语言提供了malloc函数。

函数语法形式:

void* malloc (size_t size);

这个函数能够向内存开辟一块连续可用的空间,并且会返回指向这块内存空间的指针。

  1. 如果内存开辟成功,则会返回指向这块开辟好的内存的指针。
  2. 如果内存开辟失败,则会返回NULL,所以当我们使用malloc函数时,一定要检查是否开辟成功。
  3. malloc函数的返回类型是void* ,这是因为malloc函数并不知道程序员要开辟内存空间的类型,所以当程序员使用时由自己决定返回类型。
  4. 如果size为0,这一行为是标准未定义的,而且也没必要,最终的结果也是编译器决定的。

使用malloc函数需要包含头文件:

#include<stdlib.h>

我们可以使用malloc来开辟下内存空间:


#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	//使用if语句来判断是否开辟成功,如果失败则提示错误信息以及提前结束
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//...... 

	return 0; 
}

我们进行调试看看是否开辟成功?

在这里插入图片描述

我们看到已经内存开辟成功了,这些值都是cd,也就是一些随机值。

但是malloc只是这样使用吗,其实并不是,malloc是需要搭配free函数使用的。接下来,就让我们介绍free函数吧~ ⬇️


🔖2.2 free

C语言提供了free函数,那么free函数有什么用❓,我们在前边介绍了malloc函数,是用来向内存申请空间的,那么free函数就是专门用来对动态内存开辟的空间进行释放和回收。
在生活中,我们都知道有借有还,再借不难。那么在内存中也是这个道理。


free函数的原型如下:

void free (void* ptr);
  1. 如果参数ptr指向的内存空间不是动态内存开辟的,那么free函数的行为是未定义的。
  2. 如果参数ptr是NULL,则函数什么事都不做。

free和malloc所包含的头文件一样。

#include<stdlib.h>

如何与malloc搭配使用❓❓❓

代码如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//使用...... 

	//释放内存空间
	free(p); 
	p = NULL; 

	return 0; 
}

这样free函数就能够释放p所指向的动态内存开辟的内存空间,那么为什么还需要把p置为NULL呢?

是因为,free函数虽然已经释放掉了开辟的内存空间,但是指针p还是指向这一空间,为了避免野指针,所以置为了NULL。


🔖2.3 calloc

动态内存开辟的函数不仅仅是malloc函数,C语言还提供了另一种函数:calloc

calloc函数原型:

void* calloc (size_t num, size_t size);
  1. 函数有2个参数,第一个 num 为个数,第二个 size 为字节大小,那么它会开辟程序员所要求的内存空间,并且把空间的每一个字节初始化为0(malloc,值都是cd(随机值))。
  2. 当内存开辟成功,返回的是指向该内存的指针;失败时,返回NULL ,所以当我们使用时,也和malloc一样,需要检查。

calloc函数如何向内存申请空间呢?让我们接着往下看⬇️⬇️⬇️

当我需要向内存申请40个字节大小时:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//calloc向内存申请40个字节空间  
	int* p  = (int*)calloc(10, sizeof(int)); 
	//判断是否开辟成功
	if (p == NULL)
	{
		perror("calloc"); 
		return 1; 
	}
	//使用..... 
	

	//释放内存空间
	free(p); 
	p = NULL;    
	return 0;
}

结果如何? 让我们来调试看看吧~

在这里插入图片描述

我们观察到,calloc函数向内存开辟的40个字节成功,并且每一个字节初始化为0。

calloc函数和malloc函数都是向内存申请空间,既然是申请,那么也需要归还内存空间,一样的都是需要free函数释放把内存还给系统。


🔖2.4 realloc

在前边,我们介绍了malloc函数和calloc函数以及free函数,最后我们介绍realloc函数。

那么我们需要先了解,realloc函数有什么用存在的意义是什么?

其实是为了让动态内存开辟更加的灵活,有时候,我们使用malloc或者calloc申请内存空间时,可能到某一时间段发现空间太大了或者不够用小了。
那么为了对内存空间进行调整,C语言呢就提供了realloc函数,这样我们就可以对内存的大小进行灵活的调整。


realloc函数原型:

void* realloc (void* ptr, size_t size);
  1. ptr是需要调整的内存地址
  2. size是调整后的大小
  3. 返回值为调整后的内存起始位置
  4. 这个函数调整会在原内存空间的基础上,还会将原来内存中的数据移动到新的内存空间
  5. realloc函数在调整内存空间时,会分为2中情况:
    情况1:当原有空间之后有着足够大的空间,那么就会在原有空间的基础上,调整大小。
    情况2:当原有空间之后没有足够大的空间,那么会另开辟一块新的空间,并且把原有空间移到新空间,再进行调整,原有空间会被释放
    在这里插入图片描述

那么如何使用realloc函数开辟内存空间? 接着往下看吧~⬇️⬇️⬇️

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//malloc向内存开辟40个字节
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//发现不够用,那么使用realloc函数调整内存大小
	//调整为80个字节
	int* ptr = (int*)realloc(p, 20 * sizeof(int));  
	if (ptr != NULL)
	{
		p = ptr; 
		ptr = NULL;  
	}
	else
	{
		perror("realloc"); 
		return 1; 
	}

	//使用..... 



	//释放内存空间
	free(p);
	p = NULL;

	return 0;
}

是否开辟成功?我们进行调试看看

在这里插入图片描述

我们可以看到之前malloc函数开辟的内存为40个字节,经过realloc函数调整大小后,为80个字节。


👋结束语

非常感谢您花时间阅读我的博客,希望我的分享能为您带来收获。如果您对本文有任何想法或疑问,欢迎在评论区留言交流。如果您喜欢我的博客,请继续关注,我会定期更新更多精彩内容。最后,别忘了行动起来的力量,让我们一起实践这些方法,见证自己的成长和进步!

那么到此,关于动态内存开辟就讲解完了~

再见,祝您生活愉快!

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新精简版】SpringCloud面试篇

文章目录 SpringBoot和SpringCloud什么区别 ?你们项目为什么要使用微服务Spring Cloud 5大组件有哪些&#xff1f;&#x1f44d;什么是微服务?微服务的优缺点是什么?你们项目中微服务之间是如何通讯的? &#x1f44d;服务注册和发现是什么意思&#xff1f;Spring Cloud 如何…

第二证券A股重要变化!今起实施

A股系列重要指数迎来样本股调整&#xff01; 此前&#xff0c;深交所及其全资子公司深证信息发布公告&#xff0c;将对深证成指、创业板指、深证100&#xff08;以下统称“深市中心指数”&#xff09;施行样本股定时调整。此次调整于6月17日&#xff08;今日&#xff09;正式施…

数据分析中的数学:从基础到应用20240617

数据分析中的数学&#xff1a;从基础到应用 数据分析离不开数学的支持&#xff0c;统计学和概率论是其重要组成部分。本文将通过几个具体的实例&#xff0c;详细讲解数据分析中常用的数学知识&#xff0c;并通过Python代码演示如何应用这些知识。 1. 描述性统计 基本概念和用…

VL53L4CD TOF开发(4)----单次测量(One-Shot)模式

VL53L4CD TOF开发.4--单次测量&#xff08;One-Shot&#xff09;模式 概述视频教学样品申请完整代码下载实现demo硬件准备技术规格系统框图应用示意图生成STM32CUBEMX选择MCU串口配置IIC配置 XSHUTGPIO1X-CUBE-TOF1app_tof.c详细解释主程序演示结果 概述 最近在弄ST和瑞萨RA的…

Spark常见的可以优化的点

Shuffle 复用 # 1.以下操作会复用的shuffle结果&#xff0c;只会读一遍数据源 val rdd1 sc.textFile("hdfs://zjyprc-hadoop/tmp/hive-site.xml").flatMap(_.split(" ")).map(x > (x,1)).reduceByKey(_ _).filter(_._2 > 1) rdd1.count() rdd1.fil…

H5小程序视频编辑解决方案,广泛适用,灵活部署

如何在微信小程序、网页、HTML5等WEB场景中实现轻量化视频制作&#xff0c;满足多样化的运营需求&#xff0c;一直是企业面临的挑战。美摄科技凭借其在视频编辑领域的深厚积累和创新技术&#xff0c;为企业量身打造了一套H5/小程序视频编辑解决方案&#xff0c;助力企业轻松应对…

函数(上)(C语言)

函数(上&#xff09; 一. 函数的概念二. 函数的使用1. 库函数和自定义函数(1) 库函数(2) 自定义函数的形式 2. 形参和实参3. return语句4. 数组做函数参数 一. 函数的概念 数学中我们其实就见过函数的概念&#xff0c;比如&#xff1a;一次函数ykxb&#xff0c;k和b都是常数&a…

Java17 --- SpringSecurity之OAuth2

一、OAuth2 1.1、使用github以授权码方式 1.1.1、注册应用程序 1.1.2、测试代码 pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId></dependency> spring…

python flask配置数据库并进行orm操作 flask_sqlalchemy

&#x1f308;所属专栏&#xff1a;【Flask】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点…

LeetCode | 28.找出字符串中第一个匹配项的下标 KMP

这是字符串匹配问题&#xff0c;朴素做法是两重遍历&#xff0c;依次从主串的i位置开始查看是否和模式串匹配&#xff0c;若不匹配就换下一个位置进行判断&#xff0c;直到找到或者遍历完&#xff0c;时间复杂度 O ( m n ) O(m \times n) O(mn) 还可以对主串进行处理&#xff…

第一个 JavaFX 应用程序

在本教程中&#xff0c;我将向你展示如何创建您的第一个 JavaFX 应用程序。因此&#xff0c;本教程既可以向你介绍核心 JavaFX 概念&#xff0c;也可以为你提供一些 JavaFX 代码&#xff0c;你可以将其用作你自己的实验的模板。 JavaFX 应用程序类 JavaFX 应用程序需要一个主…

【论文复现|智能算法改进】基于多策略融合灰狼算法的移动机器人路径规划

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】灰狼算法&#xff08;GWO&#xff09;原理及实现 2.改进点 混沌反向学习策略 融合Logistic混沌映射和Tent混沌映射生成Logistic-Tent复合混沌映射: Z i 1 { ( r Z i ( 1 − Z i ) ( 4 −…

下载mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar操作教程

1、下载地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 2、截图如下

中华老字号李良济,展现百年匠心之魅力,释放千年中医药文化自信

6月14-16日&#xff0c;“潮品老字号 国货LU锋芒”江苏老字号博览会在南京隆重启幕&#xff0c;中华老字号李良济凭借过硬的品牌实力和优质的口碑再次受邀参加&#xff0c;并在展会上绽放百年匠心魅力&#xff0c;彰显千年中医药文化自信&#xff01; 百年匠心 以实力铸就荣耀…

Autosar诊断-FIM模块功能介绍

文章目录 前言一、FIM模块概述二、FID概念介绍Event ID和DTC之间的关系Event ID与FID之间的关系FIM数据结构三、FiM模块与SW-C模块交互关系四、FIM模块函数调用关系FiM功能模块作用过程前言 Autosar诊断的主体为UDS(Unified Diagnostic Services)协议,即统一的诊断服务,是…

linux如何部署前端项目和安装nginx

要在Linux上部署前端项目并安装Nginx&#xff0c;你可以按照以下步骤操作&#xff1a; 安装Nginx: sudo apt update sudo apt install nginx 启动Nginx服务: sudo systemctl start nginx 确保Nginx服务开机自启: sudo systemctl enable nginx 部署前端项目&#xff0c;假设前…

PromptMRG: Diagnosis-Driven Prompts for Medical Report Generation

文章汇总 存在的问题 罕见疾病在训练数据中的代表性不足&#xff0c;使其诊断性能不可靠。 解决办法 1&#xff1a;利用预训练的CLIP模型从数据库中检索相似的报告来辅助查询图像的诊断。 2&#xff1a;设计SDL模块根据不同疾病的学习状态自适应调整优化目标。 流程解读 文…

MPLS VPN一

R1为客户&#xff0c;现在进行一些基本配置&#xff0c;来确保可以通路由 先启动OSPF跑通 在R3上 等一会 现在启动MPLS 对R3 对R4 然后在R2上 再把接口划到空间里面 原来的IP在公网里面&#xff0c;被清除了 然后再配置接口 查看 对R1&#xff08;相当于客户&#xff09; …

2024年最易被破解的密码TOP50,你中招了吗?

今天&#xff0c;我们要聊聊一个每个人都会用到&#xff0c;但可能并不那么重视的话题——密码安全。密码&#xff0c;这个看似简单的字符组合&#xff0c;其实与我们的信息安全、财产安全密切相关。想象一下&#xff0c;如果你的手机、邮箱、银行账户等都被一个简单的密码保护…