C语言——动态内存分配

news2024/9/23 3:26:19

        前言:通过前面的学习,我们知道C语言中在内存中开辟空间的方法有:变量和数组。既然拥有了开辟空间的方法,我们为什么还要学习动态内存分配呢?

int val = 20;  //在内存中开辟四个字节的空间
int arr[10] = { 0 }; //在内存中开辟四十个字节的连续空间

        变量和数组确实可以在内存中开辟空间,但它们也有一些不足的点 :①、开辟的空间大小是固定的,②、数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。但很多时候我们无法一开始就知道程序到底需要多少内存,使用数值和变量当程序需要的内存变大时,数组和变量开辟的空间是无法变大的,满足不了程序的需求,动态内存正是在这样的基础上诞生。

        一、动态内存函数:

1.1malloc和free:

1.1.1mall函数语法和使用:

malloc函数语法:

 malloc函数作用:动态开辟内存,可以向内存申请一块连续可以的空间,并返回指向这块空间的指针。

malloc开辟空间指针返回注意点:

        如果间开辟成功时,返回指向该空间的指针。
        如果开辟空间失败,返回一个NULL指针。
        malloc函数的返回值类型为:void* 类型,malloc函数不会指定开辟空间的类型,具体类型由使用者决定。

函数头文件:        stdlib.h 

C++plus地址:malloc - C++ 参考 (cplusplus.com)

int main()
{
	int* p = (int*)malloc(40);
	return 0;
}

空间打印演示:

int main()
{
	int* p =(int*) malloc(40);
    //判断空间是否开辟成功

	if (p == NULL)
	{
		perror("malloc"); //开辟失败报错
		return 1;
	}
    //开辟成功
	int i = 0;
	for ( i = 0; i < 10; i++)
	{
		printf("%d\n",*(p+1)); //以十进制打印指针内容
	} 
	return 0;
}

代码里面的 int* p =(int*) malloc(40); 与int arr[10] 具有相同的效果,int类型为4个字节,10个int类型的数据刚好大小为40个字节。

malloc函数开辟内存块的大小,以字节为单位。是无符号整数类型(size_t);

malloc申请的空间在内存中的存储位置:

malloc申请空间后 :

malloc 申请到空间后,直接返回的是这快空间的起始地址,不会初始化该空间的内容。所以是上面的代码打印过程中,我们会发现打印的值为一些不正常的数字。

int main()
{
	int* p = (int*)malloc(40);

	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for ( i = 0; i < 10; i++)
	{
		*(p+i) = i;
	}
	for ( i = 0; i < 10; i++)
	{
		printf("%d ",*(p+i));
	}
	free(p);
	return 0;
}

        上面代码中最后在完成打印数据时,书写了free(p); 的语句,当我们将它去掉,在VS中就行打印时,视乎也没有什么特别大的问题,但这里却必须要使用它,这是为什么呢?

1.1.2 free函数:

free函数语法:

void free (void* ptr);

        free函数的作用:动态内存的释放和回收。

free函数注意点:

        ①、如果ptr指向的空间不是动态开辟的,那么函数free的行为就是未定义行为。

        ②、如果参数ptr是NULL指针,则函数什么事情都不用做。

函数头文件:stdlib.h

 C++plus地址:free - C++ 参考 (cplusplus.com)

1.2calloc和realloc函数:

        前面我们学习了malloc同态内存开辟,calloc函数的作用也是进行动态内存开辟的.

calloc函数语法:

 函数功能:开辟num个大小为size的元素开辟一块空间,并且会将空间的每个字节初始化为0。

int main()
{
	int* p = (int*)calloc(10, sizeof(int)); //calloc动态空间开辟,大小40字节
	if (p == NULL)
	{
		perror("calloc"); //错误检测
	}
    //打印数据
	int i = 0;
	for ( i = 0; i < 10; i++)
	{
		printf("%d ",p[i]);
	}
	free(p);
	return 0;
}

realloc函数语法:

         ptr 是要调整的内存地址,size调整之后新大小。

        realloc的返回值为调整后的内存起始位置。

        realloc函数不仅会调整原内存空间大小,还会将原来内存中的数据移动到新的空间。

realloc函数调整内存空间的两种情况:

        ①、原有空间之后有足够大的空间。

直接在原有内存之后追加空间,原空间的数据不变。 

        ②、原有空间之后没有足够大的空间。

第二种情况时,会开辟新的空间,并且将就的空间中的数据拷贝到新的空间中,释放旧的空间,并且返回新空间的地址。 

函数使用代码:

int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	//初始化为1~10
	int i = 0;
	for ( i = 0; i < 10; i++)
	{
		p[i] = i + 1;
	}
	//扩展空间
	int* ptr = realloc(p,80);
	if (ptr != NULL)
	{
		p = ptr;
	}
	return 0;
}

1.3常见的动态内存错误:

        1.对NULL指针进行解引用操作:

int main()
{
	int* p = (int*)malloc(INT_MAX/4);
	*p = 20;
	free(p);
}

 2、对动态开辟的空间越界访问:

int main()
{
	int i = 0;
	int* p = (int*)malloc(10*sizeof(int));
	if (NULL == p)
	{
		perror(malloc);
	}
	for ( i = 0; i <= 10; i++)
	{
		*(p+i) = i;
	}
	free(p);
}

3、对非动态开辟内存使用free释放:

int main() 
{
	int a = 10;
	int* p = &a;
	free(p);
}

4、同一块空间多次释放: 

int main()
{
	int i = 0;
	int* p = (int*)malloc(10*sizeof(int));
	if (NULL == p)
	{
		perror(malloc);
	}
	for ( i = 0; i < 10; i++)
	{
		*(p+i) = i;
	}
	free(p);
	p = NULL;
	free(p); //错误地方。
	return 0;
}

5、动态内存开辟忘记释放:(内存泄漏)

int main()
{
	int* p =(int*) malloc(40);
    //判断空间是否开辟成功

	if (p == NULL)
	{
		perror("malloc"); //开辟失败报错
		return 1;
	}
    //开辟成功
	int i = 0;
	for ( i = 0; i < 10; i++)
	{
		printf("%d\n",*(p+1)); //以十进制打印指针内容
	} 
	return 0;
}

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

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

相关文章

AI探索实践16 - Typescript开发AI应用8:为大模型增加记忆(Memory)

大家好&#xff0c;我是feng&#xff0c;欢迎关注公众号和我一起探索。如果文章对你有所启发&#xff0c;请为我点赞、转发以及在下方留言自己的理解&#xff01; 每次发文章都看到不少人收藏。我自己也有这个习惯&#xff0c;但是基本上收藏起来的东西都没再打开过。哪怕再遇到…

Vite为什么比Webpack快

一、引言 主流的前端构建工具包括以下几种&#xff1a; Webpack&#xff1a;当下最热门的前端资源模块化管理和打包工具。它能够将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。同时&#xff0c;Webpack还支持代码分割&#xff0c;可以按需加载模块&#…

普林斯顿算法讲义(四)

原文&#xff1a;普林斯顿大学算法课程 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 6.1 事件驱动模拟 原文&#xff1a;algs4.cs.princeton.edu/61event 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 本章节正在建设中。 根据弹性碰撞的法则使用事件驱动…

STM32使用常见错误合集(正在更新版)

本文章记录一些学习STM32的一些错误问题 一、编译、烧录类问题 1、烧录不成功&#xff0c;Keil提示RDDI-DAP Error【场景&#xff1a;PWM驱动直流电机】 解决方案&#xff1a;将电机断开再进行烧录&#xff0c;断开后就可以美美烧录不报错啦~ 二、Keil使用问题 1、打开一个…

中宣部防沉迷系统PHP版本(管局防沉迷验证-PHP-全版本-接口测试样例)

现在对接游戏&#xff0c;无论是登录还是支付都是要去对接防沉迷实名认证接口&#xff0c;但前期的话你要登录网络游戏防沉迷实名认证系统进行接口测试&#xff0c;$appid &#xff0c;$bizId&#xff0c;$key去接口测试页面找&#xff08;正式上线在密钥管理&#xff09;&…

2024.3.14

1、成员函数版本实现算术运算符的重载 全局函数版本实现算术运算符的重载 #include <iostream>using namespace std;class Team {friend const Team operator-(const Team &t1, const Team &t2); private:int a;int b; public:Team(){}Team(int a, int b):a(a…

建筑安全监测系统解决方案-GNSS位移监测站

方案背景 房屋建筑安全是人们生产、经营、居住、学习、娱乐等经济生活和人身安全的基本保证。近年来&#xff0c;房屋安全事故频发&#xff0c;造成了人员伤亡和极大财产损失。因此&#xff0c;在保护居民的人身安全和财产安全方面&#xff0c;房屋建筑安全管理就显得尤为重要…

python--字符串切片和常用的写法

python--字符串切片和常用的写法 正序切片格式注意点 倒序切片格式 字符串运算字符串转义字符串常用方法大小写相关的统计相关的拆分&替换字符串连接&#xff08;面试&#xff09;字符串格式化 正序切片 格式 str1[起始索引:结束索引]左闭右开&#xff08;取左边下标的值&…

python 调用redis创建查询key

部署redis apiVersion: apps/v1 # 描述api版本&#xff0c;默认都用这个 kind: Deployment # 资源类型&#xff0c;可以配置为pod&#xff0c;deployment&#xff0c;service&#xff0c;statefulset等等 metadata: # deployment相关的元数据&#xff0c;用于描述deployment的…

2024哥本哈根major跟以往有什么区别?

2024哥本哈根major跟以往有什么区别&#xff1f; 时隔将近300天&#xff0c;CS2的第一场major终于即将到来。在预选赛中&#xff0c;来自世界各地成千上万支队伍经历过一层又一层的厮杀搏斗&#xff0c;最终遴选出这24支最顶尖的战队&#xff0c;将于3月17日齐聚于哥本哈根的皇…

C#_Array数组_多维数组_交错数组

文章目录 C#数组类型分析多维数组交错数组数组的属性和方法上期习题答案本期习题 C#数组 数组是一个用来存储相同类型数据的、固定大小的、具有连续内存位置的顺序集合。数组中的每个元素都对应一个索引值&#xff0c;索引从 0 开始依次递增&#xff0c;我们可以通过索引来访问…

html5的css使用display: flex进行div居中的坑!

最近做项目的时候&#xff0c;有个需求&#xff0c;一个高度宽度不确定的Div在另一个Div内上下左右居中。 然后以前上下居中用的都是很繁琐的&#xff0c;就打算去百度搜索一个更优秀的方法。 百度AI自己给我一个例子&#xff1a; /* div在容器里居中显示&#xff0c;设置外容…

如何零基础入门Prometheus

本公众号的精品教程《玩转Prometheus监控》是一套零基础的入门教程&#xff0c;基于多年实战经验编写而成&#xff0c;内容完整覆盖了产品的核心技术要点&#xff0c;适合想入门和进阶技术的朋友学习。 整个系列总共24篇课程&#xff0c;由基础知识开始&#xff0c;逐步进阶学…

IDEA编写各种WordCount运行

目录 一、编写WordCount(Spark_scala)提交到spark高可用集群 1.项目结构 2.导入依赖 3.编写scala版的WordCount 4.maven打包 5.运行jar包 ​6.查询hdfs的输出结果 二、本地编写WordCount(Spark_scala)读取本地文件 1.项目结构 2.编写scala版的WordCount 3.编辑Edit …

mupdf渲染过程(一):颜色

mupdf除了解析PDF功能之外&#xff0c;还有一个强大的功能就是渲染文字和图像&#xff0c;本文介绍mupdf渲染过程中涉及到的颜色问题&#xff1a;包括颜色空间&#xff0c;颜色转换&#xff0c;lcms的使用。 1.初始化 mupdf初始化第一步是实例化fz_context *ctx&#xff0c;fz…

2W10-ASEMI适配器专用2W10

编辑&#xff1a;ll 2W10-ASEMI适配器专用2W10 型号&#xff1a;2W10 品牌&#xff1a;ASEMI 封装&#xff1a;WOB-4 最大重复峰值反向电压&#xff1a;1000V 最大正向平均整流电流(Vdss)&#xff1a;2A 功率(Pd)&#xff1a;中小功率 芯片个数&#xff1a;4 引脚数量…

钡铼技术有限公司R40路由器工业4G让养殖环境监控更高效

钡铼技术有限公司的R40路由器是一款专为养殖环境监控而设计的工业级4G路由器。该路由器的出现极大地提高了养殖行业的监控效率&#xff0c;为养殖场主和管理者提供了更可靠、高效的解决方案。本文将从功能特点、优势以及应用案例等方面介绍钡铼技术有限公司的R40路由器在养殖环…

【SpringBoot】自定义工具类实现Excel数据新建表存入MySQL数据库

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

hololens2发布unity设置

生成vs工程再向hololens发布时&#xff0c; Architecture选X64或ARM64都可以成功发布

python-0002-linux安装pycharm

下载软件包 下载地址&#xff1a;https://download.csdn.net/download/qq_41833259/88944791 安装 # 解压 tar -zxvf 你的软件包 # 进入软件解压后的路径&#xff0c;如解压到了/home/soft/pycharm cd /home/soft/pycharm cd bin # 执行启动命令 sh pycharm.sh # 等待软件启…