C语言---动态内存管理

news2025/7/19 17:36:55

C语言—动态内存管理

文章目录

  • C语言---动态内存管理
  • 1. 为什么要进行动态内存分配
    • 1.1 动态内存管理所在的区域
  • 2. 动态内存函数的介绍
    • 2.1 malloc
      • 2.1.1 malloc语法
      • 2.1.2 malloc具体实例
    • 2.2 free
      • 2.2.1 free语法
      • 2.2.2 free具体实例
    • 2.3 calloc
      • 2.3.1 calloc语法
      • 2.3.2 calloc具体实例
    • 2.4 realloc
      • 2.4.1 realloc语法
      • 2.4.2 realloc调整空间时存在的情况
      • 2.4.3 realloc具体实例
  • 总结


1. 为什么要进行动态内存分配

我们已经掌握的内存开辟方式有:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

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

1.1 动态内存管理所在的区域

在这里插入图片描述

2. 动态内存函数的介绍

2.1 malloc

2.1.1 malloc语法

void* malloc (size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己
    来决定。
  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

2.1.2 malloc具体实例

代码如下(示例):

#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	//申请40个字节,用来存放10个整型
	int* p = (int*)malloc(40);
	//malloc函数语法格式上返回类型是void* ,但原因是因为开发者为使用者留存的一个可以自己改变的类型的方式
	//所以当使用malloc函数的时候,要清楚自己存放的类型是什么。同样要记住进行强制类型转换
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//存放1--10
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;
	}
	//打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

2.2 free

2.2.1 free语法

void free (void* ptr);

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

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

2.2.2 free具体实例

首先在上述malloc代码中存在一个隐患,就是在向内存空间申请40个字节的时候,如果代码结束运行之后操作系统会回收40个字节的空间,但是如果代码一直在运行,并且申请的40字节的内存已经用完不想在使用的时候,就会造成内存浪费,这个时候就需要free函数去释放申请的内存空间。

代码如下(示例):

#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	//申请40个字节,用来存放10个整型
	int* p = (int*)malloc(40);
	//malloc函数语法格式上返回类型是void* ,但原因是因为开发者为使用者留存的一个可以自己改变的类型的方式
	//所以当使用malloc函数的时候,要清楚自己存放的类型是什么。同样要记住进行强制类型转换
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//存放1--10
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;
	}
	//打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	//free是释放申请的内存
	free(p);
	p = NULL;//主动将释放后的p指针赋值NULL,防止非法访问
	return 0;
}

2.3 calloc

2.3.1 calloc语法

void* calloc (size_t num, size_t size);
  • 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
  • 函数 malloc 申请到的空间没有初始化,直接返回起始地址, calloc 会在返回地址之前把申请的空间的每个字节初始化为全0

在这里插入图片描述

2.3.2 calloc具体实例

#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	int* pi = (int*)malloc(40);
	int* p = (int*)calloc(10, sizeof(int));
	if (NULL == p)
	{
		perror("calloc");
		return 1;
	}
	if (pi == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(pi + i));
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	//释放
	free(p);
	free(pi);
	p = NULL;
	pi = NULL;
	return 0;
}

2.4 realloc

2.4.1 realloc语法

有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。

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

2.4.2 realloc调整空间时存在的情况

  • 情况1:原有空间之后有足够大的空间
  • 情况2:原有空间之后没有足够大的空间
    在这里插入图片描述
  • 当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
  • 当是情况2的时候,realloc函数会找一个满足空间大小的新的连续空间,把旧的空间的数据,拷贝新空间的前面的位置,并且把旧的空间释放,同时返回新的空间地址
  • realloc如果扩容失败,就返回空指针

2.4.3 realloc具体实例

#include<errno.h>
#include<string.h>
#include<stdlib.h>

int main()
{
	int* pi = (int*)malloc(5*sizeof(int));
	if (NULL == pi)
	{
		perror("malloc");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*(pi + i) = 1;
	}
	//不够了,再增加5个整型
	int* ptr = realloc(pi, 10 * sizeof(int));//需要用新的指针来接收,防止扩容失败把旧的数据弄丢
	if (ptr != NULL)
	{
		pi = ptr;
	}
	//继续使用空间
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(pi+ i));
	}
	//释放空间
	free(pi);
	pi = NULL;
	return 0;
}

在这里插入图片描述


总结

  1. 在使用动态内存函数的时候要记得判断指针是都为NULL,否则容易出现问题。
  2. 在动态内存开辟之后,要及时使用free函数将其释放。

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

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

相关文章

基于Linux操作系统中的MySQL数据库SQL语句(三十一)

MySQL数据库SQL语句 目录 一、SQL语句类型 1、DDL 2、DML 3、DCL 4、DQL 二、数据库操作 1、查看 2、创建 2.1、默认字符集 2.2、指定字符集 3、进入 4、删除 5、更改 6、练习 三、数据表操作 &#xff08;一&#xff09;数据类型 1、数值类型 1.1、TINYINT …

【C++】总结3

文章目录 1.类的访问限定符2.封装3.类对象的存储方式4.为什么要进行内存对齐&#xff1f;结构体怎么对齐&#xff1f;5.如何让结构体按照指定的对齐参数进行对齐6.如何知道结构体中某个成员相对于结构体起始位置的偏移量7.C有哪几种构造函数8.类的六个默认成员函数9.构造函数10…

web-xss

HTML的< >&amp;&quot;©分别是<&#xff0c;>&#xff0c;&&#xff0c;"&#xff0c;©;的转义字符 XML只有5个转义符: < >&amp; &quot; &apos; HTTP请求中&#xff0c;Referer是header的一部分&#xff0c;当浏览器…

【防火墙】iptables防火墙(二)

1.写在命令行的备份和还原 2.把我们的规则配置在服务的文件当中&#xff0c;形成永久生效 iptables-save > /opt/ky30.bak iptables-restore < /opt/ky30.bak cat /etc/sysconfig/iptables 永久生效的配置文件 自定义链&#xff1a; 1.创建自定义链&#xff1a; i…

【数据结构】---时间复杂度与空间复杂度

时间复杂度与空间复杂度 1.&#x1f4c9; 时间复杂度&#x1f4cc;1.1 时间复杂度的概念1.2 大O的渐进表示法 &#x1f3f0;空间复杂度&#x1f4c3;例题分析1.案例&#xff08;常数阶&#xff09;2.案例&#xff08;线性阶&#xff09;3.案例&#xff1a;&#xff08;平方阶&a…

香港中文大学多媒体实验室——人工智能与计算机视觉的创新引擎

原创 | 文 BFT机器人 01 引言 香港中文大学多媒体实验室&#xff08;MultimediaLaboratory&#xff09;成立于2001年7月&#xff0c;是香港中文大学信息工程学系的重要组成部分。该实验室由汤晓鸥教授执导&#xff0c;是最早应用深度学习进行计算机视觉研究的华人团队之一。因…

Latex | 将MATLAB图并导入Latex中的方法

一、问题描述 用Latex时写paper时&#xff0c;要导入MATLAB生成的图进去 二、解决思路 &#xff08;1&#xff09;在MATLAB生成图片的窗口中&#xff0c;导出.eps矢量图 &#xff08;2&#xff09;把图上传到overleaf的目录 &#xff08;3&#xff09;在文中添加相应代码 三…

麒麟v10-coredns 启动失败

现象 在麒麟ARM芯片的机器上搭建k8s&#xff0c;其中的的一个组件cordons 发现启动失败&#xff0c;查看日志如下所示&#xff1a;No such device or address 问题分析 期初猜测kubelet与containerd的cgroupDriver驱动不一致导致。分别查看是一致的。没有问题。发现系统存在…

阿里云NVIDIA A100 GPU云服务器性能详解及租用费用

阿里云GPU服务器租用费用表包括包年包月、一个小时收费以及学生GPU服务器租用费用&#xff0c;阿里云GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡&#xff0c;GPU云服务器gn6i可享受3折&#xff0c;阿里云百科分享阿里云GPU服务器租用表、GPU一个小时多少…

javafx拖拽图片实现

效果 代码 package cn.juhe.zjsb.test;import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javaf…

jmeter接口自动化测试工具在企业开展实际的操作

在企业使用jmeter开展实际的接口自动化测试工具&#xff0c;建议按如下操作流程&#xff0c; 可以使整个接口测试过程更规范&#xff0c;更有效。 接口自动化的流程&#xff1a; 1、获取到接口文档&#xff1a;swagger、word、excel ... 2、熟悉接口文档然后设计测试用例&am…

SAFe工具,SAFe规模化敏捷工具,SAFe实施流程,SAFe框架管理工具

​Leangoo领歌敏捷工具覆盖了敏捷项目研发全流程&#xff0c;包括小型团队敏捷开发&#xff0c;Scrum of Scrums大规模敏捷。 随着SAFe的越来越普及&#xff0c;Leangoo本次上线提供了完整的SAFe框架功能&#xff0c;包括&#xff1a;Program Backlog&#xff0c;PI规划&#…

Linux相关指令(上)

常见指令&#xff1a; 1 pwd&#xff1a;查看用户当前所在目录 以下面的路径为例&#xff1a; 2 ls&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。 对于文件&#xff0c;将列出文件名以及其他信息 ls-l&#xff08;or ll&#xff09;&#xff1a;列…

插槽slot复习

1.认识插槽 ◼ 在开发中&#xff0c;我们会经常封装一个个可复用的组件&#xff1a;  前面我们会通过props传递给组件一些数据&#xff0c;让组件来进行展示&#xff1b;  但是为了让这个组件具备更强的通用性&#xff0c;我们不能将组件中的内容限制为固定的div、span等等…

学生公寓报修管理系统的设计与实现(论文+源码)_kaic

摘 要 随着科技的发展&#xff0c;信息化的管理手段早以在人们生活的各个方面取代了传统的管理手段&#xff0c;以先进管理理念为基础的现代化信息管理系统已经成为了许多机构的必备工具。在如今大学的校园里&#xff0c;有着许许多多的信息化管理系统&#xff0c;如图书管理系…

面试官:Redis 为什么变慢了?怎么解决?

一、Redis为什么变慢了 二、Redis如何优化 三、Redis变慢了排查步骤 一、Redis为什么变慢了 1.Redis真的变慢了吗&#xff1f; 对 Redis 进行基准性能测试 例如&#xff0c;我的机器配置比较低&#xff0c;当延迟为 2ms 时&#xff0c;我就认为 Redis 变慢了&#xff0c;…

Qt : day2

1. #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {qDebug() << this->size(); //获取当前页面尺寸this->setFixedSize(500, 600); //设置固定尺寸this->setWindowTitle("聊天框"); //设置窗口标题thi…

快速批量处理,高效添加水印的软件推荐

辛迪&#xff1a;嘿&#xff0c;你听说过加水印技术吗&#xff1f; 杰克&#xff1a;当然啦&#xff01;那是一种在图像或视频上添加标识的技术&#xff0c;对吧&#xff1f; 辛迪&#xff1a;没错&#xff01;加水印技术可以在作品上添加标识、文字、图像等&#xff0c;以保…

Python实现HBA混合蝙蝠智能算法优化XGBoost回归模型(XGBRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蝙蝠算法是2010年杨教授基于群体智能提出的启发式搜索算法&#xff0c;是一种搜索全局最优解的有效方法…

【计算机】磁盘基础知识

一、背景前言 今年2023年&#xff0c;已经是机械硬盘诞生的第67个年头了。作为存储数据的硬件设备&#xff0c;它的发展可谓历经了很多人的努力&#xff0c;在这个过程中也发现很多有意思的事情。通常在生活中&#xff0c;不太懂计算机的朋友们常把内存与硬盘的概念混淆&#…