C语言中的动态内存管理

news2025/1/15 7:52:00

在C语言中,动态内存管理是通过一系列的标准库函数来实现的,这些函数包括malloc, free, callocrealloc。它们允许程序在运行时动态地分配和释放内存,这是管理复杂数据结构(如链表、树等)时非常有用的功能。

为什么存在动态内存分配

一些常规的内存开辟方式有:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
但是上述的开辟空间的方式有两个特点:
  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道, 那数组的编译时开辟空间的方式就不能满足了。这时候就只能试试动态存开辟了。

malloc

C 语言提供了一个动态内存开辟的函数:
void* malloc (size_t size);

malloc函数用于分配一块指定大小的内存区域。分配的内存是原始的,即未初始化,其中的值是未定义的。

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。如果开辟成功则返回一个指向开辟好空间的指针。如果开辟失败则返回一个NULL指针,因此一定要检查malloc的返回值。

返回值的类型是 void* ,所以 malloc 函数并不知道开辟空间的类型,具体在使用的时候使用者自己
来决定。 如果参数 size 0 malloc 的行为是标准是未定义的,取决于编译器。

free函数可以返回之前通过malloc等函数分配的内存。free(ptr)释放ptr指向的内存块。释放后,ptr不再指向一块有效的内存。

void free (void* ptr);

free函数用来释放动态开辟的内存。

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数 ptr NULL指针,则函数什么事都不做。

示例:
 

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int*)malloc(sizeof(int)); // 分配一个整数大小的内存
    if(ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    *ptr = 10; // 在分配的内存中存储值
    printf("Value at ptr: %d\n", *ptr);
    
    free(ptr); // 释放内存
    ptr = NULL; 
    return 0;
}

这段代码使用malloc分配了足够存储一个整数的内存。然后检查malloc返回的指针,确保内存分配成功。接着在分配的内存中存储一个值,最后使用free释放内存,防止内存泄漏。

calloc

C语言还提供了一个函数叫calloccalloc函数与 malloc类似,但有两个不同点:它接受两个参数,用于指定元素的数量和每个元素的大小,并且分配的内存区域会自动初始化为零。
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为 0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int *p = (int*)calloc(10, sizeof(int));
 if(NULL != p)
 {
 //使用空间
 }
 free(p);
 p = NULL;
 return 0;
}

所以如果对申请的内存空间要求初始化,则可以很方便的使用calloc函数完成任务。

realloc

realloc函数用于重新调整之前分配的内存块的大小。这可以用于增大或减小内存块。它的出现让动态内存管理更加灵活。比如有时候觉得申请的空间过大或者过小,这时候要对内存的大小做灵活的调整。realloc函数可以做到对动态开辟内存大小的调整。

void* realloc (void* ptr, size_t size);

ptr是要调整的内存地址,size是调整之后的新大小。返回值为调整之后的内存起始位置。这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

realloc 在调整内存空间的是存在两种情况:
  • 情况 1:原有空间之后有足够大的空间。要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
  • 情况2:原有空间之后没有足够大的空间 。原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。

示例:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int*)malloc(2 * sizeof(int)); // 初始分配2个整数大小的内存
    if(ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    ptr[0] = 1;
    ptr[1] = 2;
    
    // 重新调整为4个整数大小的内存
    int *new_ptr = (int*)realloc(ptr, 4 * sizeof(int));
    if(new_ptr == NULL) {
        printf("Re-allocation failed\n");
        free(ptr);
        return 1;
    }
    
    new_ptr[2] = 3;
    new_ptr[3] = 4;
    
    for(int i = 0; i < 4; i++) {
        printf("%d ", new_ptr[i]); // 打印新分配的数组
    }
    
    free(new_ptr); // 释放内存
    return 0;
}

首先通过malloc分配了一个有2个整数的数组。然后使用realloc增加这个数组的大小至4个整数。在新分配的内存中存储更多的值,然后打印出新的内存块中的所有值。最后使用free释放内存。

需要注意的是每次调用malloc, callocrealloc最终都需要调用free来释放内存,以避免内存泄漏。

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

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

相关文章

为何要3次握手?TCP协议的稳定性保障机制

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

MYSQL练题笔记-聚合函数-每月交易

一、题目相关内容 1&#xff09;相关的表和题目 2&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、初步的理解 是需要知道每个月和每个国家/地区的事务数及其总金额&#xff0c;每个月和每个国家/地区已批准的事务数及其总金额&#xff1b;以上的理解还是…

RPC和REST对比

RPC和REST对比 参考学习 RPC 和 REST 之间有什么区别&#xff1f; 当我们对比RPC和REST时&#xff0c;其实是在对比RPC风格的API和REST风格的API&#xff0c;后者通常成为RESTful API。 远程过程调用&#xff08;RPC&#xff09;和 REST 是 API 设计中的两种架构风格。API …

【计算机组成原理】存储器知识

目录 1、存储器分类 1.1、按存储介质分类 1.2、按存取方式分类 1.3、按信息的可改写性分类 1.4、按信息的可保存性分类 1.5、按功能和存取速度分类 2、存储器技术指标 2.1、存储容量 2.2、存取速度 3、存储系统层次结构 4、主存的基本结构 5、主存中数据的存放 5.…

分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测

分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测 目录 分类预测 | Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量输入数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现FA-SVM萤火虫算法优化支持向量机的多变量…

网络安全现状

威胁不断演变&#xff1a; 攻击者不断变化和改进攻击方法&#xff0c;采用更复杂、更隐秘的技术&#xff0c;以逃避检测和追踪。这包括新型的勒索软件、零日漏洞利用和社交工程攻击等。 供应链攻击&#xff1a; 攻击者越来越关注供应链的弱点&#xff0c;通过在供应链中植入恶…

Gitee拉取代码报错You hasn‘t joined this enterprise! fatal unable to access

文章目录 一、问题二、解决2.1、进入**控制面板**2.2、进入**用户账户**2.3、进入**管理Windows凭据**2.4、**普通凭据**2.4.1、添加2.4.2、编辑 2.5、重新拉取|推送代码 三、最后 一、问题 Gitee拉取仓库代码的时候报错You hasnt joined this enterprise! fatal unable to ac…

小米秒享3--非小米电脑

小米妙享中心是小米最新推出的一款功能&#xff0c;能够为用户们提供更加舒适便利的操作体验。简单的说可以让你的笔记本和你的小米手机联动&#xff0c;比如你在手机的文档&#xff0c;连接小米共享后&#xff0c;可以通过电脑进行操作。 对于非小米电脑想要体验终版秒享AIOT…

Spring Task 定时任务框架

Spring Task Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位&#xff1a;定时任务框架 作用&#xff1a;定时自动执行某段Java代码 Spring Task使用步骤 1). 导入maven坐标 spring-context&#xff08;已存在&#xff…

如何在忘记密码的情况下恢复解锁 iPhone

您忘记了 iPhone 密码吗&#xff1f;Apple 官方通常建议将 iPhone 恢复至出厂设置以将其删除。这种修复很不方便&#xff0c;甚至可能比问题本身更麻烦。 如果您也经历过同样的情况&#xff0c;并且想知道忘记了 iPhone 密码并且不想恢复它该怎么办&#xff0c;我们的终极指南…

本项目基于Spring boot的AMQP模块,整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ

在业务逻辑的异步处理&#xff0c;系统解耦&#xff0c;分布式通信以及控制高并发的场景下&#xff0c;消息队列有着广泛的应用。本项目基于Spring的AMQP模块&#xff0c;整合流行的开源消息队列中间件rabbitMQ,实现一个向rabbitMQ添加和读取消息的功能。并比较了两种模式&…

Flutter PK jetpack compose区别和选择

Flutter诞生于Chrome团队&#xff0c;是一帮做Web的开发做的跨平台框架&#xff0c;从最开始的设计初衷&#xff0c;就是指向了跨平台这条路&#xff0c;而Compose&#xff0c;则是诞生于Android团队&#xff0c;是为了解决当前View的架构体系不能再继续适应申明式编程的范式而…

Nginx的反向代理与负载均衡

概念介绍 1). 正向代理 正向代理服务器是一个位于客户端和原始服务器(origin server)之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向代理发送一个请求并指定目标(原始服务器)&#xff0c;然后代理向原始服务器转交请求并将获得的内容返回给客户端。 …

如何购买阿里云服务器

作为一家全球领先的云计算服务提供商&#xff0c;阿里云提供了多种云产品和解决方案&#xff0c;包括云服务器、对象服务OSS、数据库、存储、SSL、域名和CDN等。阿里云服务器是一种灵活可扩展的云计算服务&#xff0c;适用于各种规模和类型的企业和个人用户。阿里云以其出色的性…

专业课:递归非递归中序遍历

非递归中序遍历二叉树通常使用栈来辅助实现。 树结构&#xff1a; struct TreeNode {int data;TreeNode* left;TreeNode* right; };递归 void inorderTraversal(TreeNode *root){if(root ! nullptr){//中序遍历 “左孩子--根节点--右孩子”inOrder(root->lchild);printf(…

「Swift」类淘宝商品瀑布流展示

前言&#xff1a;需要做一个类似于淘宝商品页面的瀑布流展示 结构分析&#xff1a; ps&#xff1a;图片来源 思路分析&#xff1a; 该瀑布流主要还是基于UICollectionView进行展示&#xff0c;只是在cell展示的UICollectionViewFlowLayout需要进行相应调整和自定义&#xff…

[ 云计算 | AWS 实践 ] 使用 Java 检查指定的密钥是否存在于给定的 Amazon S3 存储桶中

本文收录于【#云计算入门与实践 - AWS】专栏中&#xff0c;收录 AWS 入门与实践相关博文。 本文同步于个人公众号&#xff1a;【云计算洞察】 更多关于云计算技术内容敬请关注&#xff1a;CSDN【#云计算入门与实践 - AWS】专栏。 本系列已更新博文&#xff1a; [ 云计算 | …

Linux——基本指令(一)

写在前面&#xff1a; 我们云服务器搭建的Linux系统&#xff0c;使用的镜像版本CentOS 7.6,使用的Xshell远程连接云服务器 前面我们使用超级管理员root账号登录&#xff0c;一般我们使用普通用户登录&#xff0c;那么如何创建新用户呢&#xff1f; 1.创建新用户 &#xff08…

【Java 基础】17 集合

文章目录 1.基本概念2.核心接口3.常见实现1&#xff09;List 接口的实现类ArrayListLinkedListVector 2&#xff09;Set 接口的实现类HashSetLinkedHashSetTreeSet 3&#xff09;Queue 接口的实现**类**ArrayQueue 4&#xff09;Map 接口的实现类HashMapLinkedHashMapTreeMap 4…

跟着Nature Communications学习Hisat-Trinity-PASA等分析流程

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 详细教程请访问&#xff1a; 组学分析流程 本期分析流程 Hisat2-SamtoolsTrinity_GG_denovoPASA … 本期教程文章 题目&#xff1a;Genomic insights into local adaptation and future climate-induced vu…