C语言动态内存管理(上)

news/2025/4/26 13:15:23/

欢迎拜访:雾里看山-CSDN博客
本篇主题:C语言动态内存管理(上)
发布时间:2025.3.16
隶属专栏:C语言

在这里插入图片描述

目录

  • 为什么需要动态内存管理
    • 静态分配的局限性
    • 动态分配的优势
  • 动态内存函数
    • malloc
      • 函数介绍
      • 函数使用
    • free
      • 函数介绍
      • 函数使用
    • calloc
      • 函数介绍
      • 函数使用
    • realloc
      • 函数介绍(C11标准)
      • 函数使用

为什么需要动态内存管理

静态分配的局限性

静态数组:int arr[100] 需要编译时确定,且空间开辟是固定的
自动变量:函数内定义的局部变量生命周期受限于函数栈帧

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。这时候就只能试试动态存开辟了。

动态分配的优势

  • 运行时按需分配(如根据用户输入决定数据规模)
  • 灵活调整内存大小(动态扩容/缩容)
  • 突破栈空间限制(堆空间通常比栈大得多)
  • 实现跨函数的数据持久化(如链表节点)

动态内存函数

malloc

函数介绍

函数地址:malloc
函数格式void* malloc (size_t size);
功能:分配一个大小字节的内存块,返回一个指向该块开头的指针。新分配的内存块的内容没有初始化,保留不确定的值。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。
头文件strstr函数的声明在stdlib.h的头文件中,在使用时,要使用#include <stdlib.h>操作包含头文件。
特别注意

  1. 如果size为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。
  2. 该指针的类型始终为void*,可以将其强制转换为所需的数据指针类型,以实现可解引用。

函数使用

#include <stdio.h>      
#include <stdlib.h>     int main()
{int i, n;char* buffer;printf("How long do you want the string? ");scanf("%d", &i);buffer = (char*)malloc(i + 1);if (buffer == NULL) exit(1);for (n = 0; n < i; n++)buffer[n] = rand() % 26 + 'a';buffer[i] = '\0';printf("Random string: %s\n", buffer);free(buffer);return 0;
}

在这里插入图片描述

free

函数介绍

函数地址:free
函数格式void free (void* ptr);
功能:释放了先前通过调用malloccallocrealloc分配的内存块,使其再次可用以进行进一步分配。
返回值void
头文件strstr函数的声明在stdlib.h的头文件中,在使用时,要使用#include <stdlib.h>操作包含头文件。
特别注意

  1. 如果ptr没有指向由上述函数分配的内存块,则会导致未定义的行为。
  2. 如果ptr是空指针,则该函数不执行任何操作。
  3. free函数没有改变ptr本身的值,因此它仍然指向相同的(现在无效的)位置。

函数使用

#include <stdlib.h>     int main()
{int* buffer1, * buffer2, * buffer3;buffer1 = (int*)malloc(100 * sizeof(int));buffer2 = (int*)calloc(100, sizeof(int));buffer3 = (int*)realloc(buffer2, 500 * sizeof(int));free(buffer1);free(buffer3);return 0;
}

在这里插入图片描述

calloc

函数介绍

函数地址:calloc
函数格式void* calloc (size_t num, size_t size);
功能:为包含num个元素的数组分配一块内存,每个元素的size为字节大小,并将其所有位初始化为零。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。
头文件strstr函数的声明在stdlib.h的头文件中,在使用时,要使用#include <stdlib.h>操作包含头文件。
特别注意

  1. 如果size为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。
  2. 该指针的类型始终为void*,可以将其强制转换为所需的数据指针类型,以实现可解引用。

函数使用

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

在这里插入图片描述

realloc

函数介绍(C11标准)

函数地址:realloc
函数格式void* realloc (void* ptr, size_t size);
功能:改变ptr所指向的内存块的大小。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针,表示ptr所指向的块没有被修改。
头文件strstr函数的声明在stdlib.h的头文件中,在使用时,要使用#include <stdlib.h>操作包含头文件。
特别注意

  1. 如果size为0,则返回值取决于特定的库实现:它可以是空指针,也可以是其他不能解引用的位置。
  2. 如果ptr是空指针,则该函数的行为类似于malloc,分配一个新的大小字节块并返回一个指向其起点的指针。
  3. 如果函数分配请求的内存块失败,则返回空指针,并且参数ptr指向的内存块不会被释放(它仍然有效,其内容不变)。
  4. 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 的空间。
  5. realloc在调整内存空间的是存在两种情况:
    情况1:原有空间之后有足够大的空间
    情况2:原有空间之后没有足够大的空间
    在这里插入图片描述
    情况1:当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
    情况2:当是情况2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
    由于上述的两种情况,realloc函数的使用就要注意一些。

函数使用

#include <stdio.h>      
#include <stdlib.h>    int main()
{int* p = (int*)malloc(40);if (p == NULL){perror("malloc");return 1;}//初始化为1~10int i = 0;for (i = 0; i < 10; i++) {p[i] = i + 1;}//增加一些空间int* ptr = (int*)realloc(p, 8000);if (ptr != NULL){p = ptr;ptr = NULL;}else{perror("realloc");return 1;}//打印数据for (i = 0; i < 20; i++){printf("%d\n", p[i]);}//释放free(p);p = NULL;return 0;
}

在这里插入图片描述

⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!


http://www.ppmy.cn/news/1579781.html

相关文章

基于SSM+Vue+uniapp的科创微应用(可改为研学)小程序+LW示例

1.项目介绍 系统角色&#xff1a;管理员、企业、普通用户功能模块&#xff1a;用户管理、企业管理、场地管理、场地类型管理、预约参观管理、场地预约管理、活动信息管理、报名信息管理、试题管理、试卷管理等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&…

理解光场模型:uv与st的结合

在计算机图形学和计算机视觉领域&#xff0c;光场模型是一种强大的技术&#xff0c;它允许我们捕捉和呈现复杂的三维场景&#xff0c;以更真实的方式表达光的传播和交互。本文将探讨光场模型的基本概念&#xff0c;并深入分析其中两个关键平面——uv平面和st平面&#xff0c;它…

linux 下消息队列

文章目录 &#x1f4e8; Linux System V 消息队列实战一、消息队列核心概念 &#x1f4a1;1. 消息队列特点 &#x1f31f;2. 生命周期 &#x1f504; 二、项目概述三、完整代码实现1. 公共头文件 common.hpp2. 发送端 sender.cpp3. 接收端 receiver.cpp 三、编译与运行指南1. 编…

初探 Threejs 物理引擎CANNON,解锁 3D 动态魅力

简介 Cannon.js 是一个基于 JavaScript 的物理引擎&#xff0c;它可以在浏览器中模拟物理效果。它支持碰撞检测、刚体动力学、约束等物理效果&#xff0c;可以用于创建逼真的物理场景和交互。 参考文档 官方示例 原理 Cannon.js 使用了欧拉角来表示物体的旋转&#xff0c;…

【误差理论与可靠性工程】可靠性工程基本理论

可靠性工程是一种工程学科&#xff0c;主要涉及如何对产品和系统的可靠性进行评估、设计和管理等。可靠性工程的基本理论包括可靠性的定义、可靠性的特征、可靠性的评估方法、可靠性的设计原则和可靠性预测方法等。 1. 可靠性的定义 可靠性是指产品或系统在规定条件下保持正常…

1.5.3 掌握Scala内建控制结构 - for循环

Scala的for循环功能强大&#xff0c;支持单重和嵌套循环。单重for循环语法为for (变量 <- 集合或数组 (条件)) {语句组}&#xff0c;可选筛选条件&#xff0c;循环变量依次取集合值。支持多种任务&#xff0c;如输出指定范围整数&#xff08;使用Range、to、until&#xff0…

DeepSeek:技术教育领域的AI变革者——从理论到实践的全面解析

一、技术教育为何需要DeepSeek&#xff1f; 在数字化转型的浪潮下&#xff0c;技术教育面临着知识更新快、实践门槛高、个性化需求强三大核心挑战。传统的教学模式难以满足开发者快速掌握前沿技术、构建复杂系统能力的需求。DeepSeek作为国产开源大模型的代表&#xff0c;凭借…

一周学会Flask3 Python Web开发-SQLAlchemy查询所有数据操作-班级模块

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们来新建一个的蓝图模块-班级模块&#xff0c;后面可以和学生模块&#xff0c;实现一对多的数据库操作。 blueprint下新建g…