动态分配内存

目录

前言

一.malloc,free函数

1.malloc,free函数原型

2.使用方法

3.具体实例

4.注意事项

二.calloc函数

1.calloc函数原型

2.主要特点

3.使用案例

三.realloc函数

1.realloc函数原型

2.使用案例

3.注意事项


前言

动态内存是指在程序运行时,按需分配和释放的内存空间。这种内存分配不在编译时固定,而是在程序执行过程中,根据实际需要分配,并且可以手动释放。

以下介绍的函数都包含于头文件<stdlib.h>

为什么使用动态内存?

1.灵活性高。动态内存可以根据需要分配内存块。

2.避免浪费内存。动态内存允许程序根据需要分配精确的内存量,从而更有效地使用内存资源。

一.malloc,free函数

malloc 是 C 标准库中用于动态内存分配的函数。它从堆(heap)中分配指定字节数的内存,并返回指向这块内存的指针。如果内存分配失败,它会返回 NULL

free 函数是C标准库中的一个函数,用于释放由动态内存分配函数(如 malloccallocrealloc)分配的内存。它的作用是将不再需要的动态内存归还给操作系统,防止内存泄漏

1.malloc,free函数原型

void* malloc(size_t size);

  • size:要分配的内存大小,以字节为单位。
  • 返回值:成功时,返回指向已分配内存块的指针;失败时,返回 NULL
  • void*:返回值类型

void free(void* ptr);

  • 参数:

    • ptr:一个指向要释放内存块的指针,这个指针必须是通过 malloccallocrealloc 返回的指针。如果 ptrNULLfree 不会执行任何操作。
  • 返回值:

    • free 没有返回值。

2.使用方法

(1)内存分配,如:

int* p = (int*)malloc(sizeof(int)); // 为一个 int 类型变量分配内存

(2)判断是否开辟空间成功(如果没有开辟成功,直接使用指针可能回答导致程序崩溃,未定义行为等),如:

if (p == NULL) {perror("malloc");//打印错误信息的函数return 1;//分配失败,退出程序
}

(3)释放内存(防止内存泄露),如:

free(p);

(4)将指针置为空(防止指针在释放内存地址后还指向原来那个地址,相当于野指针,可能会导致未定义行为或者程序崩溃等等),:

p = NULL;

3.具体实例

#include<stdio.h>
#include<stdlib.h>
int main() {int* arr = (int*)malloc(sizeof(int) * 10);//或者int* arr=(int*)malloc(40);//判断是否分配内存成功if (arr == NULL) {perror("malloc");//打印错误信息return 1;//分配失败,退出程序}//初始赋值for (int i = 0; i < 10; i++) {arr[i] = i + 1;}//打印结果for (int i = 0; i < 10; i++) {printf("%d ", arr[i]);}//释放内存free(arr);//将arr置为空arr = NULL;return 0;
}

需要注意的是:

在int* arr = (int*)malloc(sizeof(int) * 10);这一语句中

1.(int*)是强制转换类型,将原本的返回值类型void*转化为我们需要定义的数据类型,当然这里我们定义的是int*类型的。

2.sizeof(int)*10是int类型的字节数乘以10,即我们要开辟4*10=40个字节,开辟10个整型的空间,当然我们也可以这么写malloc(40),前提是你要计算好你需要开辟的字节数,否则在没有开辟够这么多的字节数的情况下越界访问数组可能会导致程序崩溃或者无限循环等的行为。

4.注意事项

malloc开辟的空间是没有创建初始值的。

举例如下:

#include<stdio.h>
#include<stdlib.h>
int main() {int* p = (int*)malloc(sizeof(int) * 5);for (int i = 0; i < 5; i++) {printf("%d ", p[i]);}return 0;
}

结果是随机值:

二.calloc函数

calloc 是 C 语言中的标准库函数,用于动态分配内存。与 malloc 类似,calloc 也用于在堆上分配一块内存

1.calloc函数原型

void* calloc(size_t num, size_t size);

  • num:要分配的元素个数。
  • size:每个元素的大小(以字节为单位)。

2.主要特点

(1)分配并初始化内存为零

calloc 会分配一块内存,并将这块内存中的所有字节初始化为 0。这与 malloc 的行为不同,malloc 仅仅分配内存,但不对内存进行初始化,内存中的内容可能是垃圾值。

(2)两个参数

malloc 不同,calloc 需要两个参数:第一个参数是要分配的元素个数,第二个参数是每个元素的大小。malloc 只需要一个参数(总内存大小),而 calloc 的目的是让用户更加清晰地定义数组类型的内存分配。

3.使用案例

#include <stdio.h>
#include <stdlib.h>int main() {int* arr = (int*)calloc(5, sizeof(int));  // 分配5个int大小的空间,且初始化为0if (arr == NULL) {printf("Memory allocation failed!\n");return 1;}// 输出分配并初始化的数组for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);  // 输出结果将是 0 0 0 0 0}printf("\n");// 使用完成后释放内存free(arr);arr=NULL; return 0;
}

结果如图:

三.realloc函数

realloc 函数用于调整已经分配的动态内存的大小

1.realloc函数原型

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

  • ptr:指向已经通过 malloc, calloc 或者 realloc 分配的内存。如果 ptrNULLrealloc 的行为与 malloc 类似,分配一块新的内存。
  • size:新分配的内存大小,以字节为单位。如果 size 为 0,realloc 的行为与 free 类似,会释放 ptr 指向的内存。

2.使用案例

(1)扩大内存

#include <stdio.h>
#include <stdlib.h>int main() {int* arr = (int*)malloc(5 * sizeof(int));  // 分配5个int的内存if (arr == NULL) {perror("malloc");return 1;}// 初始化数组for (int i = 0; i < 5; i++) {arr[i] = i;}//第一次打印for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}printf("\n");// 调整数组大小,增加到10个intint* new_arr = (int*)realloc(arr, 10 * sizeof(int));if (new_arr == NULL) {perror("realloc");free(arr);  // 如果失败,释放原来的内存arr = NULL;return 1;}// 如果重新分配成功,继续使用新数组arr = new_arr;// 初始化新增加的部分(第二次打印)for (int i = 5; i < 10; i++) {arr[i] = i;}// 输出数组for (int i = 0; i < 10; i++) {printf("%d ", arr[i]);}printf("\n");// 释放内存free(arr);arr = NULL;return 0;
}

结果如图:

(2)缩小内存

#include <stdio.h>
#include <stdlib.h>int main() {// 分配 10 个 int 大小的内存int* arr = (int*)malloc(10 * sizeof(int));if (arr == NULL) {perror("malloc");return 1;}// 初始化数组for (int i = 0; i < 10; i++) {arr[i] = i + 1;}printf("初始10个元素:\n");for (int i = 0; i < 10; i++) {printf("%d ", arr[i]);}printf("\n");// 使用 realloc 缩小数组到 5 个 intint* new_arr = (int*)realloc(arr, 5 * sizeof(int));if (new_arr == NULL) {perror("realloc");free(arr);  // 如果 realloc 失败,释放原来的内存arr = NULL;return 1;}// 如果 realloc 成功,继续使用缩小后的数组arr = new_arr;printf("缩小后的元素:\n");for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);}printf("\n");// 释放缩小后的内存free(arr);arr = NULL;return 0;
}

结果如图:

注意事项:

  • 在缩小内存时,数组后面的数据会丢失。程序只能访问缩小后剩余的那部分数据。
  • 缩小内存后,应确保访问的索引在新分配的范围内,避免越界访问。

3.注意事项

  • 扩展/缩小内存realloc 可以扩展或者缩小已经分配的内存块。如果扩展,之前的数据会保留;如果缩小,超出部分会被释放。
  • 原内存的保留:如果 realloc 需要移动内存块(例如在当前内存空间不足的情况下),它会自动分配新内存并将旧内存的数据复制过去,原来的内存块会被释放。
  • 失败时不释放原内存:如果 realloc 失败,它不会释放原来的内存,程序可以继续使用原来的

除了这三点,我们还要注意一点,我们来看一下代码:

就是用原来的指针接收申请的空间

#include <stdio.h>
#include <stdlib.h>
int main()
{int* ptr = (int*)malloc(100);if (ptr != NULL){//业务处理 }else{return 1;}//扩展容量 ptr = (int*)realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?) free(ptr);return 0;
}

问题:

  • 如果 realloc 申请失败,会返回 NULL。此时,ptr 的原有地址(即之前分配的内存)将会被丢失,导致 内存泄漏。由于 ptr 被覆盖成 NULL,无法再释放之前申请的内存,也无法继续使用。

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

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

相关文章

51单片机学习第六课---B站UP主江协科技

DS18B20 1、基本知识讲解 2、DS18B20读取温度值 main.c #include<regx52.h> #include"delay.h" #include"LCD1602.h" #include"key.h" #include"DS18B20.h"float T; void main () {LCD_Init();LCD_ShowString(1,1,"temp…

时序必读论文14|VLDB24 TFB:全面且公平的时间序列预测方法框架

论文标题&#xff1a;TFB: Towards Comprehensive and Fair Benchmarking of Time Series Forecasting Methods 论文链接&#xff1a;https://arxiv.org/pdf/2403.20150.pdf 代码链接&#xff1a;https://github.com/decisionintelligence/TFB 前言 五一过后读的第一篇文章…

矩阵系统源码搭建的具体步骤,支持oem,源码搭建

一、前期准备 明确需求 确定矩阵系统的具体用途&#xff0c;例如是用于社交媒体管理、电商营销还是其他领域。梳理所需的功能模块&#xff0c;如多账号管理、内容发布、数据分析等。 技术选型 选择适合的编程语言&#xff0c;如 Python、Java、Node.js 等。确定数据库类型&…

计算机毕业设计 基于Python的广东旅游数据分析系统的设计与实现 Python+Django+Vue Python爬虫 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件

Qt 中的 QListWidget、QTreeWidget 和 QTableWidget&#xff1a;简化的数据展示控件 在 Qt 的用户界面开发中&#xff0c;展示和管理数据是常见的需求。Qt 提供了丰富的控件供开发者选择&#xff0c;其中 QListWidget、QTreeWidget 和 QTableWidget 是三个高层封装控件&#x…

vue实现文件解压缩

1. 使用CompressionStream API实现压缩 这里开启了多线程解压缩 <template><div class"page"><input type"file" placeholder"选择文件" id"file" /><button click"compress(compress)">压缩<…

uplink 级联口

Uplink 播报编辑讨论上传视频 交换机上的一种端口 展开2个同名词条 本词条缺少概述图&#xff0c;补充相关内容使词条更完整&#xff0c;还能快速升级&#xff0c;赶紧来编辑吧&#xff01; 在点到多点系统中&#xff0c;由分散点到集中点的传输链路。例如&#xff1a;在移动…

yolov8训练数据集——labelme的json文件转txt文件

yolov8的环境搭建&#xff0c;参考&#xff1a;Home - Ultralytics YOLO Docs 1.把标注好的json文件和jpg放同一个目录下。 2.运行转换脚本文件labelme2yolo.py文件&#xff1a; # -*- coding: utf-8 -*-import os import numpy as np import json from glob import glob im…

【C#】CacheManager:高效的 .NET 缓存管理库

在现代应用开发中&#xff0c;缓存是提升性能和降低数据库负载的重要技术手段。无论是 Web 应用、桌面应用还是移动应用&#xff0c;缓存都能够帮助减少重复的数据查询和处理&#xff0c;从而提高系统的响应速度。然而&#xff0c;管理缓存并不简单&#xff0c;尤其是当你需要处…

Linux-基础实操篇-组管理和权限管理(上)

Linux 组基本介绍 在 linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在 linux 中每个文件 有所有者、所在组、其它组的概念。 用户和组的基本概念&#xff1a; 用户名&#xff1a;用来识别用户的名称&#xff0c;可以是字母、数字组成的字符串&#xff0…

基于yolo11的工地钢筋检测计数训练、应用系统

基于yolo11的工地钢筋检测计数应用系统 基于yolo11的工地钢筋检测计数训练系统 yolov8/9/10/11模型在工地钢筋检测计数中的应用【代码数据集python环境训练/应用GUI系统】 背景意义 多数钢厂和工地普遍依靠人工来统计成捆钢筋的根数&#xff0c;这种方式不仅机械枯燥、劳动强度…

深入掌握 Protobuf 与 RPC 的高效结合:实现C++工程中的高效通信

目录 一、Protobuf与RPC框架的通信流程概述二、Protobuf与RPC在C中的实际应用2.1 定义 .proto 文件2.2 编译 .proto 文件生成C代码2.3 实现服务器端逻辑2.4 实现客户端逻辑2.5 使用CMake构建工程2.6 编译与运行2.7 关键组件解析2.8 序列化与反序列化的实现 三、关键实现与解析四…

帝都程序猿十二时辰

前言 2019年度国产剧《长安十二时辰》火了&#xff0c;其口碑榜首、节奏紧凑、贴合原著、电影质感&#xff0c;都是这部剧的亮点。而最令人震撼的还是剧中对大唐盛世的还原&#xff0c;长安街坊的市容市貌、长安百姓的生活日常、长安风情的美轮美奂……而关于十二时辰的话题也接…

Unity 2D RPG Kit 学习笔记

学习资料&#xff1a; B站教学视频&#xff1a;https://www.bilibili.com/video/BV1dC4y1o7A5?p1&vd_source707ec8983cc32e6e065d5496a7f79ee6 2D RPG Kit Documentation.pdf文档 1、2D RPG Kit Documentation文档 1.1、Scenes/TitleScreen 开始菜单工程 1.2、https://it…

C++语言学习(3): type 的概念

type 的概念 C中的变量拥有类型&#xff0c; 这是显然的。 实际上&#xff0c;每个 object&#xff0c; 每个 reference&#xff0c; 每个 function&#xff0c; 每个 expression &#xff0c; 都有对应的 type &#xff08;类型&#xff09;&#xff1a; Each object, refer…

【SQL】有至少五名直接下属的经理

目录 语法 需求 示例 分析 代码 语法 SELECT columns FROM table1 JOIN table2 ON table1.common_column table2.common_column; 在数据库管理和编程中&#xff0c;JOIN 是一种用于结合来自两个或多个表的数据的 SQL 操作。通过使用 JOIN&#xff0c;你可以根据两个表中的…

vue3 + ts 二次封装 el-menu

实现效果&#xff1a; 1. types / menu.ts export interface MenuItem {index: string,label: string,icon?: string,disabled?: boolean,children?: MenuItem[], }2. components / CustomMenu / index.vue <template><el-menu :default-active"defaultActi…

10.2 Linux_并发_进程相关函数

创建子进程 函数声明如下&#xff1a; pid_t fork(void); 返回值&#xff1a;失败返回-1&#xff0c;成功返回两次&#xff0c;子进程获得0(系统分配)&#xff0c;父进程获得子进程的pid 注意&#xff1a;fork创建子进程&#xff0c;实际上就是将父进程复制一遍作为子进程&…

傅里叶级数在机器人中的应用(动力学参数辨识)

B站首发&#xff01;草履虫都能看懂的【傅里叶变换】讲解&#xff0c;清华大学李永乐老师教你如何理解傅里叶变换&#xff0c;辨清美颜和变声原理&#xff0c;&#xff01;&#xff01;_哔哩哔哩_bilibiliB站首发&#xff01;草履虫都能看懂的【傅里叶变换】讲解&#xff0c;清…