C语言 — 动态内存管理
目录
- 1.malloc和free函数
- 1.1 malloc函数
- 1.2 free函数
- 1.3 malloc函数的使用
- 2.calloc函数
- 2.1 calloc函数
- 2.2 calloc函数的使用
- 3.realloc函数
- 3.1 realloc函数
- 3.2 realloc函数的使用
- 4.动态内存管理笔试题
- 4.1 笔试题(1)
- 4.2 笔试题(2)
- 5.柔性数组
- 5.1 柔性数组定义
- 5.2 柔性数组的使用
1.malloc和free函数
1.1 malloc函数
malloc函数的功能是向内存申请一块连续的内存空间,并将内容初始化为随机值,申请的大小是参数size,单位是字节,返回类型是void*类型的指针。
malloc函数的返回值:如果申请成功,会返回申请的内存空间起始位置的地址,如果申请失败会返回NULL(空指针).
1.2 free函数
free函数的功能是将开辟的内存空间释放,参数是开辟内存空间的起始地址,释放后参数ptr并不为NULL(空指针),因此使用free函数释放内存空间的同时,需要将ptr置为空指针;如果ptr本身为NULL,free函数不会执行。
1.3 malloc函数的使用
#include<stdio.h>
#include<stdlib.h>
//malloc函数的使用
int main()
{//开辟十个整型的空间大小//需要类型转换为int*类型的指针作为返回值int* ptr = (int*)malloc(10 * sizeof(int));//判断是否为NULL指针if (ptr == NULL){//输出错误原因perror("malloc");return 1;//终止程序}//使用for循环初始化int i = 0;for (i = 0; i < 10; i++){ptr[i] = i + 1;}//输出打印for (i = 0; i < 10; i++){printf("%d ", ptr[i]);}//释放内存空间free(ptr);ptr = NULL;//赋值为空指针return 0;
}
按F10启动调试观察malloc函数空间的开辟和释放的过程:观察开辟后内存空间的值
使用for循环初始化后的内容
输出初始化的内容1-10
按F10观察执行free函数后,开辟内存空间的内容,以及参数的变化
在使用free函数后需要及时将参数ptr置为空指针,否则会导致非法访问内存空间,导致程序奔溃。
2.calloc函数
2.1 calloc函数
calloc函数的功能与malloc一样,向内存申请一块连续的内存空间;与malloc函数不同的是,calloc函数有两个参数,第一个参数是元素个数,第二个参数是一个元素的大小,单位是字节,返回值是void*类型的指针。
如果开辟成功,返回开辟空间的起始地址,开辟失败,返回NULL(空指针)。
2.2 calloc函数的使用
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable:4996)//strcpy在VS中可能报警告,提示不安全,
//使用此指令可以不报警告,安全使用strcpy函数
//calloc的使用struct Stu
{char name[20];//名字int age;//年龄float score[3];//成绩
};
int main()
{//开辟1个结构体大小//需要类型转换为struct Stu*类型的指针作为返回值struct Stu* ptr = (struct Stu*)malloc(1 * sizeof(struct Stu));//第一个参数元素个数,第二个元素一个元素大小//判断是否为NULL指针if (ptr == NULL){//输出错误原因perror("calloc");return 1;//终止程序}float score1[3] = { 90.00f,85.50f,99.00f };//初始化strcpy((ptr->name,"Mary");//ptr->name表示name成员首元素地址ptr->age = 20;memcpy(ptr->score, score1,sizeof(score1));//ptr->score表示score成员首元素地址//输出打印printf(" name: %s\n age: %d\n score: %.2f %.2f %.2f",ptr->name, ptr->age, ptr->score[0], ptr->score[1], ptr->score[2]);//释放内存空间free(ptr);ptr = NULL;//赋值为空指针return 0;
}
按F10启动调试,观察calloc函数使用后内存空间的变化:使用calloc函数后,内存空间开辟成功,将内容初始化为随机值或者0。
初始化后
输出
free函数释放空间后,将参数置为空指针
3.realloc函数
3.1 realloc函数
realloc函数的功能是当开辟的内存空间不够或者多余时,进行内存空间的调整;第一个参数是调整空间的起始地址,第二个参数是调整后内存空间的大小,返回值是void*类型的指针。
如果开辟成功有两种情况,第一种是在原有的基础上,后面追加调整补充的空间,返回第一个参数的地址;第二种是重新开辟一块新的内存空间,将开辟的内存空间的起始地址返回;如果开辟失败返回空指针。
3.2 realloc函数的使用
#include<stdio.h>
#include<stdlib.h>
int main()
{//使用calloc开辟5个整型大小int* ptr = (int*)calloc(5, sizeof(int));//判断是否开辟失败if (ptr == NULL){perror("calloc");//输出错误内容return 1;}//调整为6个整型大小int* ptr1 = (int*)realloc(ptr, 6 * sizeof(int));if (ptr1 == NULL){//1.将原开辟的空间释放,并置空指针free(ptr);ptr = NULL;//2.输出错误信息perror("realloc");return 1;//终止程序}//释放内存空间,并置空指针free(ptr1);ptr1 = NULL;return 0;
}
按F10启动调试观察使用realloc函数后的内容变化:调用calloc函数后的内容
观察调用realloc函数后的内容
最后将空间释放,回收内存空间,最后不free(ptr)是因为,realloc函数在重新开辟新空间时,会将原有的参数开辟的空间释放,最后就不用再次释放,只需要释放调整后的内存空间。
4.动态内存管理笔试题
4.1 笔试题(1)
//以下程序的运行结果是什么?
#include <stdio.h>
#include <stdlib.h>
void GetMemory(char* p)
{p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);
}
int main()
{Test();return 0;
}
程序运行的结果是程序崩溃,因为GetMemory函数传参str,使用char*p接收,p变量是str的一份临时拷贝,
改变形参不能改变实参的值,所以在调用strcpy函数函数时,str是NULL,导致程序终止。
4.2 笔试题(2)
//以下程序的运行结果是什么?存在什么问题?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);
}
int main()
{Test();return 0;
}
程序可以正常输出hello,但是开辟内存空间后没有的释放内存空间,导致内存泄露。
5.柔性数组
5.1 柔性数组定义
柔性数组是存在于结构体中的最后一个成员,使用柔性数组的结构体必须至少包含两个成员,如下:
struct S
{int i;int arr[0];//柔性数组
};
sizeof计算时不会包含柔性数组的大小。
#include<stdio.h>
struct S
{int a;char ch[0];//柔性数组
};int main()
{printf("%zu", sizeof(struct S));return 0;
}
5.2 柔性数组的使用
#include<stdlib.h>struct Peo//人的结构体
{char name[20];//名字int age;//年龄char adress[20];//通讯地址char tele[12];//联系方式};
struct Contact//通讯录
{int count;//当前存储信息数量int capacity;//当前容量struct Peo data[0];//柔性数组(结构体数组)
};
int main()
{//开辟空间:一个整型和十个struct Peo大小struct Contact* ptr = (struct Contact*)malloc(sizeof(int) + 10 * sizeof(struct Peo));//判断if (ptr == 0){perror("malloc");return 1;}//使用//......//......//调整(内存空间不足时,根据count和capacity的值进行调整)//......//......//释放空间free(ptr);ptr = NULL;return 0;
}
柔性数组使用的好处:
1.灵活的内存管理:柔性数组允许结构体的最后一个成员是一个未知大小的数组。这意味着在动态分配内存时,可以根据实际需求来改变数组的长度,从而实现了内存的灵活管理。
2.提高访问速度:由于柔性数组直接作为结构体的一个成员,访问时不需要通过指针进行间接访问,这减少了访存次数,提高了访问速度。
3.减少内存碎片:通过动态分配内存,柔性数组可以更有效地利用内存空间,减少内存碎片的产生。
相关文章:

C语言 — 动态内存管理
目录 1.malloc和free函数1.1 malloc函数1.2 free函数1.3 malloc函数的使用 2.calloc函数2.1 calloc函数2.2 calloc函数的使用 3.realloc函数3.1 realloc函数3.2 realloc函数的使用 4.动态内存管理笔试题4.1 笔试题(1)4.2 笔试题(2)…...

《TCP/IP 详解 卷1:协议》第5章:Internet协议
IPv4和IPv6头部 IP是TCP/IP协议族中的核心协议。所有TCP、UDP、ICMP和IGMP 数据都通过IP数据报传输。IP提供了一种尽力而为、无连接的数据报交付服务。 IP头部字段 IPv4 头部通常为 20 字节(无选项时),而 IPv6 头部固定为 40 字节。IPv6 不…...
C#面向对象实践项目--贪吃蛇
目录 一、项目整体架构与核心逻辑 二、关键类的功能与关系 1. 游戏核心管理类:Game 2. 场景接口与基类 3. 具体场景类 4. 游戏元素类 5. 基础结构体与接口 三.类图 四、核心流程解析 五、项目可优化部分 一、项目整体架构与核心逻辑 该项目运用场景管理模…...

学习STC51单片机26(芯片为STC89C52RCRC)
每日一言 真正的强者,不是没有眼泪,而是含着泪依然奔跑。 硬件:4G模块 这个是接线原理,我们也只要知道这个4根线的连接就好了,我们也是连接到USB转TTL的模块上 要插卡哈......... 随后我们下载一个叫做亿佰特的调试助…...
Web前端为什么要打包?Webpack 和 Vite 如何助力现代开发?
一. 为什么要使用框架库? 1.1 传统网页与现代前端的差异 在最早期的网页开发中,我们只需要写几个.html文件,配上.css和.js文件,浏览器直接加载就能展现页面,每个文件都是独立的静态资源,简单且直观 但现在网站越来越复杂了: 需要用到最新的js语法(比如ES6)使用框架(Vue…...

Nginx详解(三):ngx_http_rewrite_module模块核心指令详解
概要: 在 Nginx 的众多功能模块中,ngx_http_rewrite_module是实现请求动态处理的核心组件,它通过一系列指令实现 URI 重写、条件判断、响应返回等功能。本文将以 CentOS 7.9 环境为例(主机名www.a.com,IP 172.25.0.10…...
C++ 建造者模式:简单易懂的设计模式解析
一、引言 在软件开发中,我们经常会遇到一些复杂对象的创建过程,这些对象通常由多个部分组成,并且每个部分的构建过程可能非常复杂。建造者模式(Builder Pattern)就是为了解决这类问题而诞生的一种创建型设计模式。本文将以简单易懂的方式介绍C++中的建造者模式,帮助你理…...

【笔记】在 MSYS2(MINGW64)中正确安装 Poetry 的指南
#工作记录 在 MSYS2(MINGW64)中正确安装 Poetry 的指南 一、背景说明 在 MSYS2(MINGW64)环境中,即使已经安装了 pip,也不建议直接使用 pip install poetry 来安装 Poetry。 这是因为 MSYS2 使用自己的包…...

IDEA项目推送到远程仓库
打开IDEA——>VCS——>Creat Git 选择项目 push提交到本地 创建远程仓库 复制地址 定义远程仓库 推送 推送成功...
DeepSeek 赋能 NFT:数字艺术创作与交易的革新密码
目录 一、NFT:数字世界的独特资产1.1 NFT 的定义与本质1.2 NFT 的价值支撑1.3 NFT 的丰富类型 二、DeepSeek:AI 领域的创新力量2.1 DeepSeek 的发展历程与成就2.2 DeepSeek 的核心技术与能力 三、DeepSeek 在 NFT 创作中的神奇应用3.1 高效生成数字艺术作…...

【后端架构师的发展路线】
后端架构师的发展路线是从基础开发到技术领导的系统性进阶过程,需融合技术深度、架构思维和业务洞察力。以下是基于行业实践的职业发展路径和关键能力模型: 一、职业发展阶梯 初级工程师(1-3年) 核心能力:掌…...

matlab/simulink TLC语法基础练习实例
一、基本语法测试方法 1.新建一个脚本,保存扩展名为tlc,本例中是tst.tlc,设置当前工作路径为保存的tlc文件路径,在tlc文件里面输入下面的代码,然后保存: %warning test 2.在MATLAB的命令窗口输入: tlc …...
MAU算法流程理解
参考文献:湘江船闸的过闸调度算法研究(李 楠,李桂华,尹剑平) (湖南湘江航运建设开发有限公司,湖南 长沙 410011) MAU算法流程 图4展示的是一种船舶排档算法(MAU算法),它…...

蓝桥杯国赛训练 day1
目录 k倍区间 舞狮 交换瓶子 k倍区间 取模后算组合数就行 import java.util.HashMap; import java.util.Map; import java.util.Scanner;public class Main {static Scanner sc new Scanner(System.in);public static void main(String[] args) {solve();}public static vo…...

ESP32之Linux编译环境搭建流程
背景:为了解决 “windows环境中编译ESP32代码速度慢” 的问题,现搭建一个Linux环境,让windows下的VScode连接到Linux环境,VSCode负责编辑代码,虚拟机用于编译代码。 目录 一、安装VMware 1.1 获取VMware安装包 1.2…...
Linux 软件安装方式全解(适用于 CentOS/RHEL 系统)
🐧 Linux 软件安装方式全解(适用于 CentOS/RHEL 系统) 在 Linux 系统中,软件安装方式丰富多样,常见于以下几种方式: 安装方式命令/工具说明软件包管理器(推荐)yum, dnf, apt, zypp…...
QT- QML Layout+anchors 布局+锚点实现窗口部件权重比例分配
布局管理 简单比较两种界面管理锚点布局实现比例布局布局管理实现比例布局循环依赖问题简谈 在日常打螺丝中,我们偶尔会需要实现界面各组件能按比例放置,自适应各种分辨率的需求。我用锚点和布局都实现过相关界面,记录下来两种方式实现的差异…...

UE5打包项目设置Project Settings(打包widows exe安装包)
UE5打包项目Project Settings Edit-Project Settings- Packaging-Ini Section Denylist-Advanced 1:打包 2:高级设置 3:勾选创建压缩包 4:添加要打包地图Map的数量 5:选择要打包的地图Maps 6:Project-Bui…...
Python中os模块详解
Python os 模块详解 os 模块提供了丰富的文件和目录操作、环境变量访问、进程管理等功能,是与操作系统交互的核心模块之一。 基本导入方式 import os常用目录与文件操作 1️⃣ 获取/设置当前工作目录 os.getcwd() # 获取当前工作目录 os.chdir(/tmp) …...

便捷高效能源服务触手可及,能耗监测系统赋能智能建筑与智慧城市
在建筑行业迈向智能化、精细化管理的进程中,传统建筑管理模式因信息割裂、数据利用不足等问题,逐渐难以满足现代建筑复杂的运营需求。楼宇自控系统实现了建筑设备的智能调控,BIM技术则构建了建筑的三维数字化模型,当两者相遇&…...
Kotlin List 操作全面指南
在传统 Java 开发 List 相关的 API 中,有着样板代码冗长、缺乏链式调用、空安全等问题。 Kotlin 这门语言 为 List 提供了丰富的扩展函数,这些函数大大简化了集合操作,解决了传统 Java 集合 API 中的许多痛点。 一、基础操作 1. 创建 List …...
C++--范围for循环详解
范围 for 循环是 C11 引入的语法特性,用于简化遍历容器或数组元素的过程。它比传统 for 循环更简洁安全,特别适合初学者。以下是详细讲解: 基本语法 for (元素类型 变量名 : 容器/数组) {// 循环体(使用变量名访问当前元素&#…...

ISO18436-2 CATII级振动分析师能力矩阵
ISO18436-2021是当前针对针对分析师的一个标准,它对振动分析师的能力和知识体系做了4级分类,这里给出的是一家公司响应ISO18436的CATII级标准,做的一个专题培训的教学大纲。摘自: 【振動噪音產學技術聯盟】04/19-23 ISO 18436-2…...
deepseek问答:torch.full() 函数详解
torch.full() 是 PyTorch 中用于创建指定形状、所有元素值都相同的新张量的核心函数。它在深度学习中有广泛应用,尤其是在初始化张量和创建特殊数据结构时。 函数签名 torch.full(size, fill_value, *, dtypeNone, layouttorch.strided, deviceNone, requires_gra…...

dvwa4——File Inclusion
LOW: 先随便点开一个文件,可以观察到url栏变成这样,说明?page是dvwa当前关卡用来加载文件的参数 http://10.24.8.35/DVWA/vulnerabilities/fi/?pagefile1.php 我们查看源码 ,没有什么过滤,直接尝试访问其他文件 在url栏的pag…...
MYSQL 高级 SQL 技巧
高级 SQL 技巧 以下是一些高级 SQL 技巧,可以帮助优化查询、提高性能并解决复杂的数据处理问题。 使用窗口函数 窗口函数允许在查询结果的行上进行计算,而不会减少行数。常见的窗口函数包括 ROW_NUMBER()、RANK()、DENSE_RANK() 和聚合函数如 SUM() 与…...

Spring Boot养老院管理系统源码分享
概述 基于Spring Boot开发的养老院管理系统,该系统通过智能化管理模块,为养老机构提供高效运营解决方案。 主要内容 后台管理功能 系统后台功能完善,左侧导航栏涵盖首页、安全巡查管理、设备管理等模块。设备管理界面以表格形式清晰展示设…...

go|context源码解析
文章目录 Context接口Deadline()Done()Err()Value() canceler接口ctxemptyCtxcancelCtxtimerCtxvalueCtx 基本使用cancelCtxvalueCtx 首先看一下源码对“context”的描述, When a Context is canceled, all Contexts derived from it are also canceled. 当一个Cont…...

如何在PowerBI中使用Analyze in Excel
如何在PowerBI中使用Analyze in Excel 之前分享过如何使用DAXStudio将PowerBI与Excel连接 ,今天介绍另外一个工具,也可以实现同样的功能,Analyze in Excel。 使用Analyze in Excel 第一步: 首先准备好一个PBIX文件,…...
【学习记录】Element UI导入报错 * element-ui/lib/theme-chalk/index.css in ./src/main.js
文章目录 📌 摘要⚠️ 问题描述🔍 原因分析✅ 正常情况下的依赖结构❗ 问题根源 ✅ 解决方案✅ 方法一:使用 cnpm 安装 Element UI(推荐)步骤 1:全局安装 cnpm(使用淘宝镜像)步骤 2&…...