C语言-动态内存分配(12.1)

news2025/1/15 6:31:58

目录

思维导图:

1.为什么存在动态内存分配

2.动态内存函数的介绍

2.1 malloc

2.2 free

2.3 calloc

2.4 realloc

3.常见的动态内存错误

写在最后:


思维导图:

1.为什么存在动态内存分配

我们现在学习了一些内存开辟的方式:

int main()
{
	int i;//在内存栈区开辟4个字节空间
	char arr[5];//在栈空间上开辟5个字节的连续空间
	return 0;
}

但是,这样开辟的内存是静态的,固定的:

1. 空间开辟大小是固定的。

2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

如果想要在编译过程中开辟空间,就需要用到动态内存。

2.动态内存函数的介绍

2.1 malloc

void* malloc (size_t size)

2.2 free

void free (void* ptr)

例:


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

int main()
{
	//申请40给字节,用来存放10个整形
	int* p = (int*)malloc(40);//malloc申请的空间不会初始化
	if (p == NULL)            //直接返回起始地址
	{
		perror("malloc");//如果空间开辟失败要报错并返回
		return 1;
	}

	//使用空间
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(p + i));
	}

	//释放申请的内存
	free(p);
	p = NULL;
	return 0;
}

输出:

输出:
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451

malloc不会自己初始化,所以打印随机值。

例:

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

int main()
{
	//申请40给字节,用来存放10个整形
	int* p = (int*)malloc(40);//malloc申请的空间没有初始化
	if (p == NULL)            //直接返回起始地址
	{
		perror("malloc");//如果空间开辟失败要报错并返回
		return 1;
	}

	//使用空间
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;//初始化赋值
		printf("%d ", *(p + i));
	}
	//释放申请的内存
	free(p);
	p = NULL;
	return 0;
}

输出:

输出:1 2 3 4 5 6 7 8 9 10

2.3 calloc

void* calloc (size_t num, size_t size)

例:

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

int main()
{
	int* p = (int*)calloc(10, sizeof(int));//10是要初始化的个数,sizeof(int)是每个的大小
	if (NULL == p)
	{
		perror("calloc");//判断内存是否申请成功
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));//calloc申请空间后,会把空间初始化成0
	}                                              //再返回起始地址

	//释放
	free(p);
	p = NULL;
}

输出:

输出:0 0 0 0 0 0 0 0 0 0

2.4 realloc

void* realloc (void* ptr, size_t size)

realloc函数可以追加更多动态内存。

例:

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

int main()
{
	int* p = (int*)malloc(5 * sizeof(int));//开辟一段动态内存20个字节
	if (NULL == p)
	{
		perror("malloc");//检查是否创建成功
		return 1;
	}
	
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*(p + i) = i + 1;
	}

	//不够用,增加5个整形的空间
	int* ptr = (int*)realloc(p, 10 * sizeof(int));//这里是开辟到40个字节
	//realloc函数开辟内存空间有两种情况:
	//1.原内存块后面空间足够,在原内存块后面追加内存
	//2.原内存块后面空间不够,另外找一片区域开辟内存,将原内存块释放

	if (ptr != NULL)
	{
		p = ptr;//为什么不直接用p接收?
		//如果内存追加失败,直接用p接收的话,原本已经开辟的动态内存空间就会被覆盖
	}

	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	//释放
	free(p);
	p = NULL;
	return 0;
}

输出:

输出:1 2 3 4 5 -842150451 -842150451 -842150451 -842150451 -842150451

3.常见的动态内存错误

例1:

开辟动态内存记得要判断,最后释放内存。

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

int main()
{
	int* p = (int*)malloc(100);
	//内存开辟后没有判断是否开辟成功
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = 0;//危险代码,我们无法知道是否存在非法访问
	}
	//并且最后也没有将开辟的内存还给操作系统
	return 0;
}

例2:

动态内存开辟了多少就用多少,小心越界访问。

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

int main()
{
	int* p = (int*)malloc(100);//开辟了100字节空间

	//判断
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	int i = 0;
	for (i = 0; i < 100; i++)//造成越界访问
	{
		*(p + i) = 0;//一个整形4个字节
	}

	//释放
	free(p);
	p = NULL;
	return 0;
}

例3:

不要乱释放其他内存空间。

int main()
{
	int a = 10;
	int* p = &a;
	//你没有权限乱释放其他的内存空间
	free(p);//不能对栈区的内存释放
	return 0;
}

例4:

不要多次释放内存空间。

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

int main()
{
	//开辟空间
	int* p = (int*)malloc(100);

	//判断
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 25; i++)
	{
		*p = i;
		p++;//p指针不断往后移动
	}

	//释放的时候指针应该指向起始地址,否则程序又会出错
	free(p);
	p = NULL;

	return 0;
}

例5:


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

int main()
{
	//创建
	int* p = (int*)malloc(100);
	
	//判断
	if (p == NULL)
	{
		return 1;
	}

	//释放
	free(p);

	free(p);//已经释放了,重复释放会导致程序出错

	return 0;
}

这就要说到最后置为空指针的好处了:

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

int main()
{
	//创建
	int* p = (int*)malloc(100);
	
	//判断
	if (p == NULL)
	{
		return 1;
	}

	//释放
	free(p);
	p = NULL;//置为空指针后程序就不会崩溃了

	free(p);//p为空指针时,程序不会报错

	return 0;
}

例5:

在实现函数时开辟了动态内存要记得及时释放或者返回地址,

不然就再也找不到那段内存空间了,最后导致内存泄漏。

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

void test()
{
	int* p = (int*)malloc(100);
	//忘记释放
}//出了函数就找不到了,因为变量p被销毁了
//造成内存泄漏

int main()
{
	test();
	return 0;
}

例6:

这道题也是类似的:

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

void test()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		return;
	}

	//使用
	if (1)
		return;//出问题//内存泄漏

	//释放
	free(p);
	p = NULL;
}

int main()
{
	test();
	return 0;
}

要小心出现内存泄漏,记得释放空间。

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

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

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

相关文章

IDEA如何把自己改动的代码一次性发给别人

背景介绍&#xff1a; 想把自己改动的代码同步给同事 方式1&#xff1a;通过git&#xff0c;把自己本地代码 push 到代码托管平台&#xff0c;同事从代码托管平台 pull 最新代码&#xff1b; 方式2&#xff1a;通过IDEA的Patch包的方式来快速发送修改的代码&#xff08;步骤如下…

pr值高的域名对网站有什么价值?怎么在线查询搜狗PR权重

众所周知一个全新的搜狗域名在建立网站后搜索引擎会对其进行一个类似资格评价的阶段&#xff0c;我们将这个阶段称为沙盒&#xff0c;在沙盒里面的这段时间&#xff0c;我们将其称为沙盒期&#xff0c;沙盒期一般都是1-3个月。在沙盒期这段时间内。我们仍需要经常更新文章。所以…

联合证券|海南自贸港快速发展,概念股出炉!

海南自由贸易港货物进出口 初次打破2000亿元关口 1月13日&#xff0c;国新办就2022年全年进出口状况举行发布会。会上介绍道&#xff0c;近两年海南自由贸易港货物进出口快速开展&#xff0c;继2021年头次打破1000亿元后&#xff0c;2022年再上新台阶&#xff0c;初次打破2000…

Pytorch深度学习【十二】

填充和步幅 卷积核带来的问题—输入形状不断减小更大的卷积核可以更快的减小输出大小 形状从nh∗nwn_h * n_wnh​∗nw​减少到 (nh−kh1)∗(nw−kw1)(n_h-k_h1)*(n_w-k_w1)(nh​−kh​1)∗(nw​−kw​1) 解决方案 填充—在输入周围添加额外的行/列—一般用0填充理论依据 填充p…

Odoo 16 企业版手册 - 库存管理之报告

报告 正确监控库存操作将帮助您轻松分析和理解库存管理的工作流程。Odoo可以为您提供一个专用平台&#xff0c;特别是用于为您的组织中完成的库存操作生成报告&#xff0c;并在图形和表格视图中准确表示数据。您可以实时自定义报告&#xff0c;以根据您的要求获得细致的报告。在…

Nvm,Nrm使用教程

NVM介绍 NVM全称node.js version management &#xff0c;专门针对node版本进行管理的工具&#xff0c;通过它可以安装和切换不同版本的node.js 使用场景 我目前的公司有很多项目&#xff0c;其中有一些老项目用的是vue2.5左右了webpack版本也比较低&#xff0c;只能使用10.16.…

[前端笔记——WEB基础] 1.WEB基本概念

[前端笔记——WEB基础] 1.WEB基本概念基本概念1.资源 resourse2.链接3.HTTP 协议4.网页的真实样子&#xff1a;HTML静态网页与动态网页1.静态网页2.动态网页现代网站架构1.网站架构当我们访问一个网站时&#xff0c;后台都会发生什么事情捏?www——万维网 www&#xff1a;Worl…

Android系统启动(三) — SystemServer处理过程

system_server 进程主要是用于创建系统服务&#xff0c;AMS、WMS、PMS 都是由它创建的。 具体来说&#xff0c;SystemServer 进程被创建后&#xff0c;主要做了以下工作&#xff1a; 启动 Binder 线程池&#xff0c;这样就可以与其他进程进行通信&#xff1b;创建 SystemServi…

JDK9下载、安装和配置环境变量图解

下载 1.输入&#xff1a;https://www.oracle.com/ 2.选择“java download” 3.点击“java archive” 下拉找到 java9 4.点击进入&#xff0c;选择windows版本 5.勾选&#xff0c;下载。需要账号下载 安装 1.双击安装包&#xff0c;下一步 2.选择安装路径&#xff0c;…

旅游景区官网(网站、小程序)小开发可以实现哪些功能?

伴随着我们生活水平的提升和手上的余钱愈来愈多&#xff0c;绝大多数人一定会选取去不同地方开展旅游&#xff0c;旅游也成為了经济发展的一大支撑。将来便捷用户和旅游业的发展趋势&#xff0c;打造出旅游景区官网&#xff08;网站、H5、小程序等&#xff09;开发设计是十分关…

【UE4 第一人称射击游戏】50-用另一种方法实现僵尸随机漫游 僵尸攻击玩家时造成伤害

上一篇&#xff1a;【UE4 第一人称射击游戏】49-僵尸攻击动画本篇效果&#xff1a;使用另一种逻辑实现了僵尸的随机漫游僵尸攻击玩家时会对玩家造成实质上的伤害步骤&#xff1a;打开“SimpleAI”&#xff0c;当僵尸看见玩家时&#xff0c;设置变量“CanSeePlayer”为False我们…

深入了解 LinkedBlockingQueue阻塞队列,分析扩容机制以及小顶堆原理

1. 前言 今天的目的是为了深入了解下优先队列的机制。不过优先队列是基于大小顶堆实现的&#xff0c;但是其本质就是一个二叉树&#xff0c;所以今天会讲一些铺垫知识&#xff0c;好了&#xff0c;废话不多说了&#xff0c;让我们开始吧 2. 前置知识 2.1 大顶堆 完全二叉树&am…

1.2、操作系统的特征

1、并发 并发\color{red}并发并发&#xff1a;指两个或多个事件在同一时间间隔内发生。 这些事件宏观上是同时发生\color{red}宏观上是同时发生宏观上是同时发生的&#xff0c;但微观上是交替发生\color{red}微观上是交替发生微观上是交替发生的。 并行\color{red}并行并行&am…

STM32F103学习笔记(10)——I2C多路复用器TCA9548A使用

一、简介 TCA9548A 器件配有八个可通过 I2C 总线控制的双向转换开关。串行时钟/串行数据 (SCL/SDA) 上行对可扩展为 8 个下行对或通道。根据可编程控制寄存器的内容&#xff0c;可选择任一单独 SCn/SDn 通道或者通道组合。这些下游通道可用于解决 I2C 从器件地址冲突。例如&…

高精度加法【c++实现】超详细讲解

高精度存在的意义 大家一定都知道int和long long是有极限的&#xff08;如下表&#xff09;&#xff0c;如果超了就无法计算正确结果了&#xff0c;那该用什么方法来计算呢&#xff1f;这就是我们今天要说的算法———高精度算法。&#xff08;本文只讲加法&#xff09; 类型…

超级浏览器的防关联效果怎么样?

很多从事跨境电商业务的朋友&#xff0c;都尝试用各种手段来防止账号关联&#xff0c;现在有很多不要钱的超级浏览器可以下载使用&#xff0c;但是很多人却不敢把高价值的账号放在超级浏览器上面&#xff0c;今天我们就来详细聊聊这个问题。说超级浏览器之前&#xff0c;我们先…

抖音世界杯直播的低延迟是怎么做到的?

动手点关注干货不迷路世界杯已经结束了&#xff0c;梅西带领阿根廷时隔三十六年之后终于如愿捧杯。抖音直播提供的 4K 超高清超低延迟看播能力给亿万观众留下了深刻的印象&#xff0c;决赛的 PCU 达到 3700w&#xff0c;在这样大规模并发下&#xff0c;如何能稳定流畅地做到更低…

GO语言配置和基础语法应用(一)

一、golang的下载和安装 这一步比较简单&#xff0c;直接打开go的官网&#xff0c;点击download即可&#xff0c;个别人打开慢可以用中国的镜像网站&#xff0c;之后访问的速度和下载第三方库的速度会快很多&#xff0c;之后傻瓜式安装一路到底即可。 配置环境变量 注意&#…

经典文献阅读之--Multi-modal Semantic SLAM(多模态语义SLAM)

0. 简介 在复杂动态环境下&#xff0c;如何去建立一个稳定的SLAM地图是至关重要的。但是现在当前的SLAM系统主要是面向静态场景。目前相较于点云的分类与分割而言。视觉的识别与分割会更加容易。这就可以根据语义信息提高对环境的理解。文章《Multi-modal Semantic SLAM for C…

JavaScript 如何正确的读懂报错信息

文章目录前言一、查看报错1.控制台报错2.终端报错二、查找错误演示总结前言 一、查看报错 如何阅读报错信息, 根据信息快速锁定错误. 1.控制台报错 红色报错信息格式: xxxx Error: xxxxx报错信息xxxxx 最终报错文件:行编号 at 最终报错方法名 (最终报错文…