当前位置:网站首页>内存==c语言1
内存==c语言1
2022-07-07 07:10:00 【栋哥修炼日记】
一、程序运行为什么需要内存
1、计算机程序运行的目的
- 结果和过程:用函数来做类比,函数的形参就是待加工的数据,函数本体是代码,函数的返回值为结果,函数的执行过程就是过程。
- 代码示例:
int add(int a,int b){ //此函数的执行为了得到结果 return a+b; } void add(int a,int b{ //此函数的执行重在过程 int c ; c=a+b; printf("c=%d\n",c); return c; } int add(int a,int b){ //此函数的执行重在过程,重在结果 int c; c=a+b; printf("c=%d\n",c); return c; }
2、计算机程序的运行过程
- 计算机程序的运行过程就是程序中多个函数相继运行的过程,函数运行的过程就是数据加工的过程。
3、冯诺依曼结构和哈佛结构
- 冯诺依曼结构:数据和代码放在一起,一起寻址。(x86)
哈佛结构:数据和代码分开放置,独立寻址。(ARM) - 代码:即函数
数据:即全局变量、局部变量 - 示例:在S5PV210中运行的Linux系统上,运行应用程序时,所有的应用程序代码和数据都放在DRAM中,这就是冯诺依曼结构;在单片机中,我们把程序烧写到Flash中。然后程序在Flash中原地运行,程序中所涉及到的数据(全局变量、局部变量)不能放在Flash中,必须放在RAM(SRAM)中,这就是哈佛结构。
4、动态内存DRAM和静态内存SRAM
- (1) DRAM的存储原理是电容存储电荷的方式,SRAM的存储原理是触发器的方式。
- (2)SDRAM:同步动态随机存储器。
5、程序运行为什么需要内存?
- 内存用来存放数据(和代码),即全局变量、局部变量等,而数据是程序得组成部分和处理对象,因此内存是程序运行的本质需求。越简单得程序运行需要得内存越小,越复杂得程序运行需要得内存越大。
- 内存管理是编程一个很重要的知识点,我们学习很多编程的关键点都是为了内存管理,比如说数据结构和算法。
6、深入思考:如何管理内存
- 从操作系统得角度说:
- 操作系统掌握着所有得硬件资源,因为内存很大,所以操作系统把内存分成一个个页面(即是块,一般是4KB),然后以页面为单位进行管理。页面内则以字节为单位进行管理。其实操作系统内存管理的原理非常复杂,但对于编程人员来说,只需要利用好操作系统提供的内存管理API即可。譬如在C语言中使用malloc、free来进行内存申请与释放
- 不带操作系统时,程序需要直接操作内存,编程者需要自己进行内存的计算和安排。
- 从编程语言的角度说:不同语言提供了不同的内存管理接口
- ①汇编:没有任何内存管理,内存管理全靠程序员自己,操作内存时直接使用内存地址,非常麻烦
- ②C语言:编译器帮我们直接管理内存地址,通过编译器提供的变量名来访问内存,操作系统下如果需要大块内存可以通过API(malloc、free)来访问系统内存,而裸机程序中需要大块内存需要自己定义数据等来解决。
- ③c++:对内存的使用进一步封装,我们可以用new来创建对象(其实就是为对象分配内存),使用完之后用delete来删除对象(即释放内存)。所以c++的内存管理比c语言更高级点,但是内存管理还是要程序员自己实现,使用完不释放会造成内存泄漏。
- ④java/c#等:这些语言不操作内存,而是通过虚拟机来操作内存。虚拟机作为我们程序员的代理,帮我们处理内存释放的工作。
- 总结:java/c#看起来似乎比c/c++更高级一些,但虚拟机的内存回收是需要付出一定性能代价的,当我们开发程序的速度非常在乎的时候,就会用java/c#等语言;当我们对程序的性能非常在乎的时候,就会用c/c++。
二、位、字节、半字、字的概念和内存位宽
1、什么是内存?
- ①硬件角度:内存实际上就是电脑的一个配件(内存条)。根据不同的实现原理,可以把内存分为SRAM和DRAM(SDRAM\DDR1SDRAM\DDR2SDRAM、LPDDR5SDRAM)
- ②逻辑角度:可以随机读写(给一个地址就可以进行访问);内存在编程中天然是用来存放变量的,c语言的一个变量就对应着内存中的一小段。
2、内存的逻辑抽象图
- 逻辑上内存是由无穷多的小格子组成,每一个小格子对应着一个地址
- 现实中的内存大小是有限制的,譬如32位的操作系统(32位系统是指32位数据线,但是一般地址线也是32位,即内存地址只有32位二进制数,所以逻辑上大小为2^32)内存限制就为4GB。实际上32位系统中的内存是小于等于4GB的。
3、位和字节、字和半字
- 内存单元的大小单位有4个:位(1bit) 字节(8bit) 半字(一般是16bit) 字(一般是32bit)
4、内存位宽
- 从硬件角度讲:内存的硬件实现本身是有宽度的,有些内存条是8位的,有些是16位的。需要强调的是内存芯片之间是可以并联的,通过并联8位的内存芯片可以实现16位或者32位的内存。(数字电路有提到过此知识)
- 从逻辑角度讲:内存位宽在逻辑上是任意的,但实际硬件的位宽不是任意的,所以我们需要按照不同位宽的硬件特性来编程
- 内存位宽是在一个时钟周期内所能传送数据的位数,位数越大则瞬间所能传输的数据量越大,这是内存的重要参数之一
三、内存编址共和寻址、内存对齐
1、内存编址方法
- 将内存单元与地址唯一地、永久地绑定起来。
- 地址和空间是内存单元的两个方面。
2、关键:内存编址是以字节为单位的
3、内存和数据类型的关系
- c语言中的数据类型有char、short、 int 、long、 float 、double。
- 数据类型是用来当定义变量的,而变量需要存储在内存中,所以数据类型必须和内存相匹配才能获得最好的性能。
- 在32位系统中定义变量最好用int,因为这样效率高。原因是系统本身就是32位的结构,一次处理32位数据。在32位系统中定义bool类型的变量时系统内部也是用int实现的。
- 在实际编程中要根据实际情况进行内存和效率的取舍。
4、内存对齐
- 对齐访问很配合硬件,所以效率很高;
- 非对齐访问因为和硬件不搭,所以效率不高
四、C语言如何操作内存
1、C语言对内存地址的封装
- 用变量名来访问内存
- 数据类型的含义:表示一个内存格子的长度和解析方法
- 函数是一段代码的封装,函数名的实质就是这一段代码的首地址,所以说函数名的本质也是一个内存地址。
2、用指针来间接访问内存
- 关于类型,不管是普通变量类型还是指针变量类型,只要记住:类型只是对后面的数字或符号(代表的是内存地址)所表征的内存的一种长度和解析方法的规定而已
3、用数组来管理内存
- 数组管理内存和变量没有本质区别,只是符号的解析方法不同。
- 数组中的第一个元素称为首元素,首元素的第一个字节的地址就是首元素首地址。
五、内存管理之结构体
1、数据结构这门学问的意义
- 数据结构就是研究数据如何在内存中组织、加工的学问。
2、最简单的数据结构:数组
- 将同种类型的变量组织起来,方便管理。
- 优势:在内存中顺序存储,可用下标随机访问。
劣势:所有元素类型必须相同,定义时必须给出大小且不能再修改。
3、结构体隆重登场
- 结构体发明出来就是为了解决数组的第一个缺陷:数组中所有元素类型必须相同。
- 代码示例:
struct people{
int age;
char name[10];
int height;
};
4、题外话:结构体内嵌指针实现面向对象(节点)
- 面向过程与面向对象:面向过程指把问题的解决步骤一步一步地拆分,按要求执行,最终解决问题;而面向对象则是把问题事务分解成各个对象,分类来解决问题。
- C语言是面向过程的,但C语言写出来的Linux系统是面向对象的。
- 用非面向对象的语言,不一定不能实现面向对象的代码,只是说用面向对象的语言来实现面向对象更加简单一些,因为语言本身就做了很多工作。
- 代码示例:
struct s{
int age;//普通变量
int(*pfunc)(void);//函数指针,指向int xxx(void)这类函数
}
//使用这样的结构体可以实现面向对象,这样包含了函数指针的结构体就类似于面向对象中的class
六、内存管理之栈(stack)
1、什么是栈?
- 栈是一种数据结构,C语言内存管理中使用栈来保存函数参数和局部变量。
2、栈管理内存的特点(小内存、自动化)
- 先进后出(FILO),而队列是先进先出(FIFO)。
- 栈的特点是入口即出口,只有一个口,另一个口是堵死的,所以是先进后出。而队列的特点是入口和出口都有,必须从入口进去,从出口出来,所以是先进先出。
3、栈的应用举例:局部变量
- c语言中的局部变量是用栈来实现的,定义局部变量,对应操作是入栈(自动化);
函数退出局部变量注销的时候,对应的操作是出栈(自动化)。 - 栈的优点:方便、分配和回收都不用程序员自己操作,c语言自动完成
- 定义局部变量但未被初始化吗,值是随机的,为什么?
因为栈式反复使用的,并且每次使用完之后没有清零
4、栈的优势和劣势
- 优势:自动化,不用程序员手动操作内存
- 劣势:首先,栈式有大小的,所以栈内存大小不好设置。所以太小怕溢出,太大怕浪费内存(与数组类似)。其次,栈溢出的危害很大,一定要避免。所以我们在C语言中定义局部变量时不能定义太多或者太大(譬如不能定义int a[10000];使用递归来解决问题时一定要注意递归收敛)。
七、内存管理之堆(heap)
1、什么是堆
- 堆是一种内存管理方式,其特点就是自由(随时申请、释放、大小块随意)
- 堆内存是操作系统划分给堆管理器(操作系统的一段代码,属于操作系统内存管理单元)来管理的,然后向使用者(用户进程)提供API(malloc和free)来使用堆内存。
- 什么时候需要使用堆内存?
需要内存容量比较大时、需要反复使用及释放时,很多数据结构(譬如链表)的使用都需要使用堆内存。
2、堆内存管理的特点
- 容量不限(常规需求都能满足)。
- 申请及释放都需要手动进行,若使用完后没有释放则会造成内存泄漏,内存泄漏的堆积会导致内存溢出甚至系统崩溃。
- (内存泄漏:申请(new/malloc)了一块内存,但是没有去手动的释放(delete/free)内存,导致指针已经消失,而指针指向的东西还在,已经不能控制这块内存)
3、C语言操作堆内存的接口
- (1)堆内存申请时有三个功能类似的函数:malloc、calloc、realloc。
- void *malloc(size_t size); // 申请指定大小的内存
- void *calloc(size_t nmemb, size_t size); // 申请nmemb个内存单元,每个size字节
- void *realloc(void *ptr, size_t size); // 改变已经申请的空间的大小
- (2)堆内存释放最简单,直接调用free函数即可
void free(void *ptr); - (3) 代码示例:
// 譬如要申请10个int元素的内存
malloc(40);
calloc(10,4);
- (4)C语言定义数组时必须给出数组元素个数,且无法再修改。而在Java等高级语言中,则可以修改数组大小,其原理是重新创建一个新的数组,然后释放掉原数组。realloc的实现原理也类似。
4、堆的优势和劣势
- 优势:灵活使用
- 劣势:需要程序员处理释放等细节,容易出错,严重依赖程序员水平。
八、复杂数据结构
1、链表、哈希表、二叉树、图等
- 链表:链表是最重要的,Linux内核中经常使用链表,驱动和应用的编写很多时候也需要链表,所以必须掌握链表:结构体的定义,链表的创建,链表的增、删、查,链表的逆序
- 哈希表:不是很常用,一般不需要自己实现,直接使用别人实现的哈希表比较多。我们需要了解哈希表的原理、特点、适用场景。
- 二叉树、图等:用于处理特定问题,很少使用,不必过于纠结。
2、为什么需要更复杂的数据结构
- 因为现实中的实际问题是多种多样的,特定的问题可能需要特定的数据结构和算法来解决。
3、数据结构和算法的关系
- 数据结构的发明都是为了配合一定的算法,算法是为了处理具体问题,其实现依赖于特定的数据结构
4、如何学习数据结构与算法
- 数据结构与算法是相符相成的,要一起研究。
- 数据结构与算法对嵌入式来说不全是重点,不要盲目地深入研究。
5、举例
- Linux内核在管理字符设备驱动时,使用了哈希表(hash table,散列表),所以字符设备驱动的很多特点都和哈希表的特点有关。
边栏推荐
- **Grafana installation**
- 面试被问到了解哪些开发模型?看这一篇就够了
- IIS redirection redirection appears eurl axd
- Niuke - Huawei question bank (61~70)
- 根据热门面试题分析Android事件分发机制(一)
- Qualifying 3
- 如何成为一名高级数字 IC 设计工程师(5-3)理论篇:ULP 低功耗设计技术精讲(下)
- Basic use of JMeter to proficiency (I) creation and testing of the first task thread from installation
- flinkcdc采集oracle在snapshot阶段一直失败,这个得怎么调整啊?
- H5网页播放器EasyPlayer.js如何实现直播视频实时录像?
猜你喜欢
flex弹性布局
VSCode+mingw64+cmake
[4g/5g/6g topic foundation-146]: Interpretation of white paper on 6G overall vision and potential key technologies-1-overall vision
Dynamics 365online applicationuser creation method change
EXT2 file system
Flex flexible layout
小程序实现页面多级来回切换支持滑动和点击操作
VSCode+mingw64
ComputeShader
Elaborate on MySQL mvcc multi version control
随机推荐
Dynamics 365online applicationuser creation method change
ViewPager2和VIewPager的区别以及ViewPager2实现轮播图
golang select机制和超时问题怎么解决
In fact, it's very simple. It teaches you to easily realize the cool data visualization big screen
Switching value signal anti shake FB of PLC signal processing series
Main (argc, *argv[]) details
C# 初始化程序时查看初始化到哪里了示例
Oracle安装增强功能出错
csdn涨薪技术-浅学Jmeter的几个常用的逻辑控制器使用
VSCode+mingw64+cmake
印象笔记终于支持默认markdown预览模式
高斯消元
Qualifying 3
Oracle installation enhancements error
Basic use of JMeter to proficiency (I) creation and testing of the first task thread from installation
esp8266使用TF卡并读写数据(基于arduino)
哈夫曼编码压缩文件
Thinkphp3.2 information disclosure
Can flycdc use SqlClient to specify mysqlbinlog ID to execute tasks
Arthas simple instructions