4.熟练使用有棱有角的内存 benben Posted on Feb 5 2023 《程序是怎样跑起来的》 ##4.1 内存的物理机制很简单 内存实际上是一种名为内存IC的电子元件。虽然IC包括DRAM、SRAM、ROM(Read Only Memory)等多种形式,但从外部来看,其基本机制都是一样的。 **内存IC**中有电源、地址信号、数据信号、控制信号灯用于输入输出的大量引脚(IC的引脚),通过为其指定地址(address),来进行数据的读写。 ##4.2 内存的逻辑模型是楼房 * 1KB内存的模型  * 变量的数据类型不同,所占用的内存大小也不一样  > 通过使用变量,即使不指定物理内存,也可以在程序中对内存进行读写。这是因为,在程序运行时,windows等操作系统会自动决定变量的物理地址。 > 如果程序只能逐个字节地对内存进行读写,那该多么不便。 此外,在不同的编程语言中,变量可以指定的数据类型的最大长度也不相同。 ##4.3 简单的指针 **指针**也是一种变量,它所表示的不是数据的值,而是存储着数据的内存的地址。 和通常的变量定义有所不同,在定义指针时,我们通常会在变量名前加一个星号(*)。 各种数据类型指针的定义 ``` char *d; //char类型的指针d的定义 short *e; //short类型的指针e的定义 long *f; //long类型的指针f的定义 ``` 数据类型表示的是从指针存储的地址中一次能够读写的数据字节数。  > 在程序中,通过明确标记数据类型来记述变量的过程称为定义变量。 > 例如,若将其记述为short a;,则表示定义了2个字节的short类型的变量。 > 变量定义后就可以进行读写了。 ##4.4 数组是高效使用内存的基础 **数组**是指多个同样数据类型的数据在内存中连续排列的形式。 作为数组元素的各个数据会通过连续的编号被区分开来,这个编号称为**索引(index)**。 指定索引后,就可以对该索引所对应地址的内存进行读写操作。而索引和内存地址的变换工作则是由编译器实现的。 ``` char g[100]; //char类型数组g的定义 short h[100]; //short类型数组h的定义 long i[100]; //long类型数组i的定义 ``` 之所以说数组是内存的使用方法的基础,是因为数组和内存的物理构造是一样的。 不同数据类型的数组  ##4.5 栈、队列以及环形缓冲区 栈和队列,都可以不通过指定地址和索引来对数组的元素进行读写。 需要临时保存计算过程中的数据、连接在计算机上的设备或者输入输出的数据时,都可以通过这些方法来使用内存。 如果每次保存临时数据都需指定地址和索引,程序就会变得比较麻烦,因此要加以改进。 ###栈和队列的区别在于数据出入的顺序是不同的。 **栈**:LIFO(Last Input First Out,后入先出) **队列**:FIFO(First Input First Out,先入先出) 1. 如果我们在内存中预留出栈和队列所需要的空间,并确定好写入和读出的顺序,就不再用指定地址和索引了。 2. 如果要在程序中实现栈和队列,就需要以适当的元素来定义一个用来存储数据的数组,以及对该数组进行读写的函数。在这些函数的内部,对数组的读写会涉及索引的管理,但从使用函数的角度来说,就没必要考虑数组及索引了。 队列一般是以环状缓冲区(ring buffer)的方式来实现的。  > 这里所说的栈并不是第1章及第10章提到的函数调用时使用的栈,而是程序员自身做成的LIFO形式的数据存储方式(该栈的实体是数组)。 ##4.6 链表使元素的追加和删除更容易 在数组的各个元素中,除了数据的值之外,通过为其附带上下一个元素的索引,即可实现**链表**。 * 链表的示例(初始状态)  * 删除链表的第3个元素的方法  * 链表中追加元素的方法  ##4.7 二叉查找树使数据搜索更有效 **二叉查找树**是指在链表的基础上网数组中追加元素时,考虑到数据的大小关系,将其分成左右两个方向的变现形式。 赠人玫瑰,手留余香 赏 Wechat Pay Alipay 5.内存和磁盘的亲密关系 3.计算机进行小数运算时出错的原因