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个字节。


👋结束语

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

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

再见,祝您生活愉快!

在这里插入图片描述


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

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

相关文章

CST软件眼图工具Eye Diagram Tools (中)--- Classical流程

距离上次眼图介绍快两年了&#xff0c;由于上期已经将重点推荐的方法&#xff08;statistical流程&#xff09;介绍了&#xff0c;所以一直没急着涉及这个话题。 仿真实例011&#xff1a;眼图工具Eye Diagram Tools&#xff08;上&#xff09; 先总结一下之前介绍过的内容&am…

容器:现代计算的基础设施

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

大模型初学者怎么入门大语言模型(LLM)?

前言 在当今的科技浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习技术已经取得了长足的进步&#xff0c;其中大模型的发展尤为引人注目。大模型&#xff0c;通常指的是拥有海量参数、能够处理复杂任务的深度学习模型&#xff0c;如自然语言处理&#xff08;…

RT-DETR 详解之 Uncertainty-minimal Query Selection

引言 在上一章博客中博主已经完成查询去噪向量构造部分的讲解&#xff08;DeNoise&#xff09;在本篇博客中&#xff0c;我们将进行Uncertainty-minimal Query Selection创新点的讲解。 Uncertainty-minimal Query Selection是RT-DETR提出的第二个创新点&#xff0c;其作用是…

UE5 Sequencer 使用指导 - 学习笔记

https://www.bilibili.com/video/BV1jG411L7r7/?spm_id_from333.337.search-card.all.click&vd_source707ec8983cc32e6e065d5496a7f79ee6 Sequencer 01 1.1 调整视口 调整窗口数量 调整视口类型为Cinematic视口 视口显示网格&#xff0c;或者条件参考线 1.2 关卡动画与…

架构设计-用户信息及用户相关的密码信息设计

将用户的基本信息和用户密码存放在不同的数据库表中是一种常见的安全做法&#xff0c;这种做法旨在增强数据的安全性和管理的灵活性。以下是这种做法的几个关键原因&#xff1a; 安全性增强&#xff1a; 当用户密码被单独存放在一个表中时&#xff0c;可以使用更强大的加密和哈…

计算机毕业设计 | SpringBoot+vue的教务管理系统

1&#xff0c;绪论 1.1 项目背景 在这个资讯高度发展的时代&#xff0c;资讯管理变革已经是一个更为宽泛、更为全面的潮流。为了保证中国的可持续发展&#xff0c;随着信息化技术的不断进步&#xff0c;教务管理体系也在不断完善。与此同时&#xff0c;伴随着信息化的飞速发展…

Hexapod C-887 使用手册 -- 1

最近要做PI C-887的集成控制&#xff0c;先把使用手册看一便&#xff0c;在此记录阅读进度。 本人微信号&#xff0c;如果有项目合作&#xff0c;可以加本人微信。 1 有关此文档 在本章中 本用户手册的目标和目标群体 符号和打印规则 图 术语的定义 其它适用文件 下载手…

Python GUI 库跨平台兼容问题及解决方案

在选择 Python GUI 库时&#xff0c;跨平台兼容性是一个重要的考虑因素。不同的 GUI 库可能在不同的操作系统上表现不同&#xff0c;因此需要选择一个能够在多个平台上运行良好的库。如果我们遇到下面的问题&#xff0c;可以尝试下我整理的方法。 1、问题背景 Python 作为一门…

基于【Lama Cleaner】一键秒去水印,轻松移除不想要的内容!

一、项目背景 革命性的AI图像编辑技术,让您的图片焕然一新!无论水印、logo、不想要的人物或物体,都能被神奇地移除,只留下纯净的画面。操作简单,效果出众,给你全新的视觉体验。开启图像编辑新纪元,尽在掌控! 利用去水印开源工具Lama Cleaner对照片中"杂质"进行去除…

【Vue】获取模块内的actions方法

目标&#xff1a; 掌握模块中 action 的调用语法 (同理 - 直接类比 mutation 即可) 注意&#xff1a; 默认模块中的 mutation 和 actions 会被挂载到全局&#xff0c;需要开启命名空间&#xff0c;才会挂载到子模块。 调用语法&#xff1a; 直接通过 store 调用 $store.di…

【Go语言】面向对象编程(一):类的定义、初始化和成员方法

面向对象编程&#xff08;一&#xff09;&#xff1a;类的定义、初始化和成员方法 1 类的定义和初始化 Go 语言的面向对象编程没有 class 、 extends 、implements 之类的关键字和相应的概念&#xff0c;而是借助结构体来实现类的声明&#xff0c;如下是定义一个学生类的方法…

Virtual Memory Primitives for User Program翻译

Virtual Memory Primitives for User Program 安德鲁阿普尔&#xff08;Andrew Appel&#xff09;和李凯&#xff08;Kai Li&#xff09; 普林斯顿大学计算机科学系 摘要 传统上&#xff0c;内存管理单元&#xff08;MMUS&#xff09;被操作系统用于实现磁盘分页的虚拟内存…

FullCalendar日历组件集成实战(9)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

一文详谈大模型 RAG 优化方案与实践

暑期实习基本结束了&#xff0c;校招即将开启。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。提前准备才是完全之策。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c…

肾合与出汗:一场你不得不关注的健康对话

设想一下&#xff0c;我们的身体就像是一部精妙复杂的交响乐&#xff0c;每一个细胞、每一个组织都是乐符&#xff0c;共同编织出生命的旋律&#xff0c;演绎着我们的过去与未来。而汗水&#xff0c;就如同交响乐中的琴弦振动&#xff0c;它流淌在我们的体表&#xff0c;记录着…

电商API接口接入||电商比价项目比价系统搭建需要注意哪些?

在搭建一个淘宝/京东比价系统时&#xff0c;需要注意以下几个方面&#xff0c;以确保系统的有效性、准确性和用户友好性&#xff1a; 确定平台和商品范围&#xff1a; 明确系统覆盖的电商平台&#xff0c;如淘宝、京东等。确定要比较的商品类别和范围&#xff0c;以确保数据的…

JFinal学习06 控制器——getPara()接收数据

JFinal学习06 控制器——getPara()接收数据 视频来源https://www.bilibili.com/video/BV1Bt411H7J9/?spm_id_from333.337.search-card.all.click 文章目录 JFinal学习06 控制器——getPara()接收数据零、JFinal数据提交的三种方式一、get提交二、post提交三、url参数化提交四、…

北航数据结构与程序设计第五次作业选填题复习

选填题考的很多都是基础概念&#xff0c;对于巩固复习一些仡佬拐角的知识点是很有用的。非北航学生也可以来看看这些题&#xff0c;这一节主要是树方面的习题&#xff1a; 一、 我们首先需要知道一个公式 这是证明&#xff1a; 知道了这个公式&#xff0c;我们把题目中的数据…