C语言——动态内存分配

        前言:通过前面的学习,我们知道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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3速查笔记

文章目录 一、创建Vue3.0工程1.使用 vue-cli 创建2.使用 vite 创建 二、常用 Composition API1.拉开序幕的setup2.ref函数3.reactive函数4.Vue3.0中的响应式原理vue2.x的响应式Vue3.0的响应式 5.reactive对比ref6.setup的两个注意点7.计算属性与监视1.computed函数2.watch函数3…

加入波卡去中心化未来计划,申请高达 2000 万美金和 500 万 DOT 激励!

在努力推进去中心化的旅途中&#xff0c;2023 年 11 月 16 日成为了一个标志性的日子。Web3 基金会 —— 一个在区块链技术和去中心化应用发展前沿不断探索和推动的组织&#xff0c;正式宣布推出去中心化未来&#xff08;Decentralized Futures&#xff09;计划&#xff0c;同时…

凝思操作系统离线安装mysql和node

PS&#xff1a;下面这就是国产凝思的界面,测试版本是V6.0.80&#xff0c;第一次听说这种系统&#xff0c;于是去官网下载部署包&#xff0c;下面是地址 注意:这个系统如果没有激活&#xff0c;ip都不会有&#xff0c;这样文件都不能传到服务器&#xff0c;xshell这些工具都连不…

redis的RDB和AOF持久化配置

RDB 持久化相关配置 Redis内部的触发RDB的机制&#xff0c;格式如下&#xff1a; # 900秒内&#xff0c;如果至少有1个key被修改&#xff0c;则执行bgsave &#xff0c; 如果是save "" 则表示禁用RDB save 900 1 save 300 10 save 60 10000 RDB的其它配置也可以…

“数据要素市场行业数智化实践系列沙龙”活动预告

在数据要素大背景下&#xff0c;随着最新的政策发布&#xff0c;有哪些行业红利和机会&#xff1f;目前行业数据应用现状如何&#xff1f;上海数商协会联合蚂蚁集团、上海数据交易所&#xff0c;打造了行业数智化实践课程&#xff0c;面向数商协会成员及数据要素从业人员&#…

景联文科技:提供通用多模态数据,助力AI多模态领域实现飞跃式发展

回顾2023年&#xff0c;以ChatGPT为代表的通用人工智能大模型在全球范围内掀起了新一轮人工智能产业发展浪潮&#xff0c;我国人工智能大模型市场呈现百“模”争鸣、日新月异的迅猛发展态势。 根据大模型之家、钛媒体数据&#xff0c;2023年中国大模型市场规模达到147亿人民币&…

Matlab|计及需求响应和电能交互的多主体综合能源系统主从博弈优化调度策略

目录 主要内容 部分代码 结果一览 下载链接 主要内容 程序建立了多主体综合能源模型&#xff0c;采用双层模型进行求解&#xff0c;上层用自适应粒子群算法求解出各能源售价和需求响应补偿价格&#xff1b;下层采用混合整数规划算法求解出三个园区、配电网、储能…

用连续自然数之和来表达整数 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 一个整数可以由连续的自然数之和来表示。给定一个整数&#xff0c;计算该整数有几种连续自然数之和的表达式&#xff0c;且打印出每种表达式。 输入描述 一个目…

[云原生] Prometheus之部署 Alertmanager 发送告警

一、Alertmanager 发送告警的介绍 Prometheus 对指标的收集、存储与告警能力分属于 Prometheus Server 和 AlertManager 两个独立的组件&#xff0c;前者仅负责定义告警规则生成告警通知&#xff0c; 具体的告警操作则由后者完成。 Alertmanager 负责处理由 Prometheus Serve…

怎么采集美团的数据

怎么使用简数采集器批量采集美团的活动、商家和商品相关信息呢&#xff1f; 简数采集器暂时不支持采集美团的相关数据&#xff0c;建议换其他网站采集&#xff0c;谢谢。 简数采集器采集网站文章数据特别高效方便&#xff0c;在简数智能向导模式下&#xff0c;只要填写要采集…

普林斯顿算法讲义(一)

原文&#xff1a;普林斯顿大学算法课程 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 1. 基础知识 原文&#xff1a;algs4.cs.princeton.edu/10fundamentals 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 概述。 本书的目标是研究各种重要和有用的算法——…

FastGPT知识库结构讲解

文章目录 FastGPT知识库结构讲解理解向量FastGPT 中向量的结构设计多向量的目的和使用方式提高向量搜索精度的方法 FastGPT 构建知识库方案导入数据方案1 - 直接分段导入导入数据方案2 - QA导入导入数据方案3 - 手动录入导入数据方案4 - CSV录入导入数据方案5 - API导入 QA的组…

SpringBoot项目根据配置文件初始化并向容器注册Bean

SpringBoot项目根据配置文件初始化并向容器注册Bean 文章目录 SpringBoot项目根据配置文件初始化并向容器注册Bean[TOC] 前言一、场景图示二、实现1.定义一个Condition实现类2.按照配置装配bean 总结 前言 在开发过程种有这种场景&#xff0c;我们在使用数据存储的时候定义了一…

智慧医疗是什么?有什么医疗信息化建设方案推荐?

近年来&#xff0c;随着云计算、物联网&#xff08;internet of things&#xff0c;IOT&#xff09;、移动互联网、大数据、人工智能&#xff08;artificial intelligence&#xff0c;AI&#xff09;、5G网络、区块链等新一代信息技术的逐步成熟和广泛应用&#xff0c;信息化已…

保姆级OpenSSL下载及安装教程

下载地址下载步骤安装步骤环境变量配置查看是否安装成功下载地址 官网链接:(https://slproweb.com/products/Win32OpenSSL.html ) 点击跳转 下载步骤 以下步骤截图,以当前官网界面为标准,后有变动请提示博主修改。 点击链接跳转后界面为 往下滚动找到安装包下载按钮…

电梯机房秀 系列二

上次小伍带大家看了部分机房的照片&#xff0c;并且简单介绍了一下电梯能量回馈装置&#xff0c;小伙伴们表示很新奇&#xff0c;没看够&#xff0c;今天小伍又来了&#xff0c;带大家看一下电梯能量回馈装置到底安装在电梯什么位置。跟着小伍去看看吧。Lets go&#xff01; 电…

算法50:动态规划专练(力扣514题:自由之路-----4种写法)

题目: 力扣514 &#xff1a; 自由之路 . - 力扣&#xff08;LeetCode&#xff09; 题目的详细描述&#xff0c;直接打开力扣看就是了&#xff0c;下面说一下我对题目的理解: 事例1&#xff1a; 输入: ring "godding", key "gd" 输出: 4. 1. ring的第…

强化学习:技术创新与应用实践

目录 前言1 强化学习原理和分类1.1 强化学习的原理1.2 基于值函数的方法1.3 基于策略的方法1.4 深度强化学习 2 强化学习应用2.1 游戏领域2.2 机器人控制2.3 金融交易 3 未来展望结语 前言 强化学习&#xff08;Reinforcement Learning&#xff09;作为人工智能领域的重要分支…

【Unity】进度条和血条的三种做法

前言 在使用Unity开发的时候&#xff0c;进度条和血条是必不可少的&#xff0c;本篇文章将简单介绍一下几种血条的制作方法。 1.使用Slider Slider组件由两部分组成&#xff1a;滑动区域和滑块。滑动区域用于显示滑动条的背景&#xff0c;而滑块则表示当前的数值位置。用户可…

数据结构:静态链表(编程技巧)

链表的元素用数组存储&#xff0c; 用数组的下标模拟指针。 一、理解 如果有些程序设计语言没有指针类型&#xff0c;如何实现链表&#xff1f; 在使用指针类型实现链表时&#xff0c;我们很容易就可以直接在内存中新建一块地址用于创建下一个结点&#xff0c;在逻辑上&#x…