【C语言进阶深度学习记录】三十三 C语言中动态内存分配

如何在程序运行的时候动态给程序分配内存?

文章目录

    • 1 动态内存分配的意义
      • 1.1 C语言中如何动态申请内存空间
      • 1.2 malloc和free的用法
      • 1.3 calloc与realloc
        • 1.31 calloc和realloc的代码案例分析
    • 2 总结

1 动态内存分配的意义

在C语言中,一切操作都是基于内存的。变量和数组名都是内存别名。但是它们的内存分配却是在编译期间由编译器决定的。定义数组的长度的时候,必须指定长度,这是在编译期间就要确定的。

但是,需求总是有的。比如当我们无法在编译期间确定到底需要多大的内存块,此时就无法定义数组的大小(或者定义的数组大小不够)。此时就需要在运行的时候根据实际的情况(比如根据输入的数据的大小),来动态的申请内存空间,然后让数组(指针)指向这块新申请的内存。

这就是动态内存分配的意义。

1.1 C语言中如何动态申请内存空间

  • malloc和free用于动态申请内存和释放内存

它们的操作对象是堆空间内存(内存池)如下图:

在这里插入图片描述

注意:malloc和free必须是成对出现的,这样可以避免内存泄露。关于内存泄露,后面还有文章进行学习。

1.2 malloc和free的用法

malloc和free的函数定义如下:

在这里插入图片描述

  • malloc所分配的是一块连续的内存,参数size是所分配的内存字节数。
  • malloc的返回值是void* ,具体使用的时候需要做强制类型转换
  • free用于将申请的动态内存归还给系统

关于malloc和free,有以下几点需要注意:

  1. malloc和free是库函数,不是系统调用
  2. malloc实际分配的内存,可能比请求的多。这是因为CPU访问内存是按照一种内存对齐的方式来访问的。所以一般申请的内存都是对齐内存的整数倍
  3. 当请求的动态内存无法满足的时候,malloc返回NULL
  4. 当free的参数为NULL的时候,函数直接返回。
  5. malloc申请的动态内存中的数据是随机值,不会被初始化为0

至于malloc和free的用法,在前面的文章已经学会使用了,这里不再给出例子,直接看前面的文章吧:二维数组与二维指针

以及在后面的文章中,会给出一个内存泄露检测模块,来巩固malloc与free的使用。自行去后面的文章查看。

1.3 calloc与realloc

函数原型为;

在这里插入图片描述

  • calloc的参数:num个类型长度为size的内存空间大小。也就是申请的内存的类型信息(大小和类型)
  • calloc会将申请的内存空间初始化为0
  • realloc用于修改原先已经分配的内存块大小
    1. 当realloc的第一个参数pointer为NULL时,realloc相当于malloc
    2. realloc一般是重新找一块新的内存块进行分配,而不是在原有的内存的结尾增加。

1.31 calloc和realloc的代码案例分析

  • 代码:38-2.c
#include <stdio.h>
#include <malloc.h>#define SIZE 5
int main() {int  i = 0;int* pI = (int*)malloc(SIZE * sizeof(int));short* pS = (short*)calloc(SIZE, sizeof(short));for (i = 0; i < SIZE; i++) {printf("pI[%d] = %d, pS[%d] = %d\n", i, pI[i], i, pS[i]);}printf("Before: pI = %p\n", pI);pI = (int*)realloc(pI, 2 * SIZE * sizeof(int));printf("After: pI = %p\n", pI);for (i = 0; i < 10; i++) {printf("pI[%d] = %d\n", i, pI[i]);}printf("\n");pS = (short*)realloc(pS, 2 * SIZE * sizeof(short));for (i = 0; i < 10; i++) {printf("pS[%d] = %d\n", i, pS[i]);}free(pI);free(pS);return 0;
}
  • 上述代码运行结果:

Linux下gcc 4.4.5编译:

在这里插入图片描述

Windows下 VS 2017运行如下:

在这里插入图片描述

  • 分析:
  1. 首先代码很很简单。无非就是使用了malloc,calloc和realloc三个函数。其中我们可以看到,在Linux下的gcc4.4.5编译器将malloc申请的内存的内容也都是0,并不是随机值。但是这只是巧合或者gcc编译器优化了而已。在windows下的vs2017编译器就很明显,malloc申请的内存的内容都是随机值
  2. 根据两个结果,可知道,使用realloc后,内存的地址变了,也就是说realloc是重新选择一块内存进行分配,并不是在原有的内存空间结尾增加
  3. 也可以看到不管是在linux下还是在windows下,calloc申请的内存的内容都被初始化为0了
  4. 从windows下的编译运行结果来看,使用realloc对之前使用calloc申请的内存重新分配内存后,原有的内容不变,但是新添加的内容并不是0,而是随机值,这个也要注意。

所以最终总结为:只有calloc胡为分配的内存的内容初始化为0,malloc和realloc都是随机值。

2 总结

  • 动态内存分配使得程序在需要的时候有机会获得更大的内存
  • malloc单纯的从系统中申请固定字节大小的内存。内存中的内容是随机值
  • calloc 申请的内存的内容被初始化为0
  • realloc用于重置内存的大小。但是是重新在堆空间中选一块内存而不是在原有的内存后面增加。并且,重置的内存中,原有的内容不变,但是如果内存变大,多余的部分的内存的内容是随机值。
  • 注意上述三者函数的参数与返回类型
  • 学会使用上述三者函数

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

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

相关文章

java并发实战

推荐一个Java并发编程实战的学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群 &#xff1a; 962535112 对于一个 Java 程序员而言&#xff0c; 能否熟练掌握并发编程是判断他优秀与否的…

a critical review of preetham skylight model 笔记

也是为了试用下Xmind。 上图是我用Xmind作的某篇文章的笔记。 感想&#xff1a; 1. 之以一直觉得这种东西没多大用处&#xff0c;回想起来大概是因为那时没有太多应用场景。 2. 如果留心&#xff0c;可以把许多事情做得更漂亮、更容易&#xff0c;这也是工具的用途。 贴一下软件…

【C语言进阶深度学习记录】三十四 C语言实现内存泄漏检测模块

上一篇文章学习了malloc系列的三个函数的使用。众所周知malloc的使用很容易导致内存泄漏。本文的目的就是使用C语言来实现内存泄漏检测模块&#xff0c;来帮忙自动检测我们写的程序中是否出现内存泄露。 文章目录1 内存泄露检测模块的实现原理1.1 各个函数模块的设计1.2 模块整…

重学前端----前端知识系统学习推荐专栏

推荐一个前端知识学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 文章目录1 概述2 专栏内容2.1 模块一&#xff0c;JavaScript2.2 模块二&#xff0c;HTML 和 …

【C语言进阶深度学习记录】三十五 程序中的堆、栈以及静态存储区(数据区)

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 在我之前学习底层的知识的时候&#xff0c;也写过相关的内容。可以对比的学习&#xff1a;【软件开发底层知识修炼】二十 深入理解可执行程序的结构&a…

【C语言进阶深度学习记录】三十六 程序与进程的区别(程序的内存布局)

上一篇文章学了堆&#xff0c;栈以及静态存储区。它们实际上都是针对进程来说的。那么程序与进程有什么区别呢&#xff1f; 本文不细讲程序与进程。 1 程序与进程 1.1 什么是程序 写完的.c文件是源文件。也叫源代码。 将源代码编译后&#xff0c;会生成可执行文件程序&#…

使用Cucumber+Rspec玩转BDD(2)——邮件激活

使用CucumberRspec玩转BDD(2)——邮件激活 2009年3月2日 星期一 ### 温故知新 ###前面我们已经完成了新用户注册功能的开发&#xff0c;为了方便我们后面的开发工作且不扰乱之前的工作成果&#xff0c;我们先将这份源代码归档并做个标记。为了获得更好的阅读体验&#xff0c;读…

【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针)

什么是野指针&#xff1f; 指针变量存的地址是一块非法内存地址。进而形成野指针。但是需要注意一点&#xff0c;野指针不是NULL指针。 文章目录1 野指针的概念1.1 野指针代码案例初探2 如何避免野指针2.1 野指针代码案例分析进阶3 总结1 野指针的概念 野指针变量中的值是非法…

算法补充 2011-9-12

设计一个算法将顺序表L中所有小于0的整数放前半部分&#xff0c;大于等于0的整数放在后半部分二叉树的删除设计一个算法将顺序表L中所有小于0的整数放前半部分&#xff0c;大于等于0的整数放在后半部分 思路:从左侧找出>0的元素&#xff0c;从右侧找出<0的元素,然后进行交…

【C语言进阶深度学习记录】三十八 C/C++语言中的函数声明与函数定义

文章目录1 函数的声明和定义1.1 代码分析2 总结1 函数的声明和定义 声明的意义在于告诉编译器程序单元的存在。只是告诉编译器它存在但是不在声明这里定义&#xff0c;有可能在当前文件中的其他地方或者其他文件中定义。如果在它还没有被定义之前就使用它&#xff0c;会导致编…

ASP.NET MVC3 系列教程 - 部署你的WEB应用到IIS 6.0

I:ASP.NET MVC3 部署的前期工作 1.确认部署的服务器操作系统环境 首先我们确认服务器的操作系统版本可以从系统命令行工具里输入: systeminfo 获取相关操作系统信息例如然后再确认IIS版本信息 -> 打开IIS管理工具即可接着确认.NET Framework的版本可以在系统命令行工具执行:…

【C语言进阶深度学习记录】三十九 C语言中的可变参数(参数可变的函数)

用过printf()函数的热都知道&#xff0c;printf的参数可以有多个&#xff0c;它是可变的&#xff0c;根据我们输出参数的类型以及个数的不同来确定参数。今天来学习C语言中参数可变的函数是如何实现的。 文章目录1 可变参数2 总结1 可变参数 首先我们要明白一点&#xff0c;在…

【离散数学中的数据结构与算法】一 最大公约数与最小公倍数之间的关系

文章目录1 算数基本定理2 最大公约数3 最小公倍数4 性质5 推论1 算数基本定理 设正整数 n>1&#xff0c; 则 n 可唯一地表示为&#xff1a; 其中 p1<p2<,…, <ps 是 s 个相异的素数&#xff0c; 指数ki都是正整数。 此定理又称作唯一析因定理&#xff08;unique f…

【离散数学中的数据结构与算法】二 欧几里得算法与裴蜀等式

欧几里得算法是计算两个数最大公因子算法。又称辗转相除法。本文将学习为什么辗转相除法可以求得两个数的最大公因子。同时也可以根据最大公因子计算两个数的最小公倍数。 文章目录1 欧几里得算法的理论基础1.1 欧几里得算法&#xff08;辗转相除法&#xff09;2 裴蜀等式&…

【离散数学中的数据结构与算法】四 加法法则与乘法法则

文章目录1 加法法则2 乘法法则3 例子3.1 例一3.2 例二3.3 例三4 总结1 加法法则 加法法则&#xff1a; 设事件 A 有 m 种产生方式&#xff0c; 事件 B 有n 种产生方式&#xff0c;则当 A 与 B 产生的方式不重叠时&#xff0c;“事件 A 或 B 之一” 有 mn 种产生方式。 加法法…

前端学习(310):清除浮动的方法

我们经常把高度塌陷问题也叫做常见的几种清除浮动的方法 高度塌陷问题—父元素高度自适应&#xff0c;子元素float后&#xff0c;造成父元素高度为0&#xff0c;就叫做高度塌陷问题 给父元素一个高度 缺点&#xff1a;无法高度自适应 父元素{overflow:hidden;} 缺点&#xf…

【离散数学中的数据结构与算法】五 排列与组合一

在leetcode刷题过程中&#xff0c;遇到过很多关于排列组合的问题。弄清楚排列组合的相关原理&#xff0c;是非常有用处的。 文章目录1 问题2 排列-有序选取2.1 重复选取-可重排列2.2 不重复选取-排列2.21 全排列3 例题4 总结1 问题 设集合S包含n个元素&#xff0c;从S中选取r个…

Google Maps 地址转化成坐标

http请求格式http://maps.google.com/maps/geo?q查询关键字&outputkml(输出格式可以 为xml kml json)&oeutf8&sensortrue或者false&key你的apikey示例http://maps.google.com/maps/geo?q湖南大学软件学院&outputkml&keyabcdefg(api key)输出kml文件如…