您现在的位置是:首页 >技术交流 >[图灵程序设计丛书].程序是怎样跑起来的--读书笔记网站首页技术交流
[图灵程序设计丛书].程序是怎样跑起来的--读书笔记
学习目标:
- 每周一本书
学习内容:
[图灵程序设计丛书].程序是怎样跑起来的--读书笔记
笔记时间:
2023-5-29-0:18
学习产出:
第1章 对程序员来说CPU是什么
1.CPU是什么?
执行程序的最终状态:机器语言(CPU会进行解释和执行)
2.CPU包含的部分
控制器、运算器、时钟、寄存器
控制器:就是控制计算机的执行的,会将内存上的指令和数据读入到寄存器中,通过指令的执行结果来控制计算机
运算器:运算从内容读入到寄存器中的数据
时钟:负责发出一些电信号,来控制计算机系统的各个部分的执行
寄存器:存储指令和数据
3.内存
通常说的都是主存,存放着正在或者即将要执行的程序和数据
DRAM:便宜 速度慢
SRAM:昂贵 速度快
4.汇编&反汇编
汇编语言和机器语言基本上是一一对应的
汇编:用汇编语言编写的程序转换成机器语言的过程
反汇编:机器语言编写的程序转换成汇编语言的过程
5.条件分支和循环机制
顺序:按序执行地址的指令
条件:按条件执行地址的指令
循环:重复执行地址的执行
6.程序中的比较指令,CPU在内部做的是减法运算
7.函数调用使用的是call指令,return命令的功能是把保存在栈中的地址设定到程序计数器中
8.通过地址和索引实现数组 --提高CPU的执行速度
基址寄存器和变址寄存器
CPU 则会把基址寄存器+变址寄存器的值解释为实际查看的内存地址
基址寄存器 会在程序运行的时候 初始化一个内存地址,通常是不可变的。
《如果没有基址寄存器,那么在进行内存操作时需要使用绝对地址。这种方法要求程序员手动指定内存地址,而且还可能需要频繁更改这些地址,从而增加代码编写和调试的难度和复杂度。》
第2章 数据是用二进制数表示的
1.IC所有引脚 只有两个状态 0和1 --这个特质决定了要使用二进制
2.b、B和bit区别
b通常指位(bit),是二进制计量中最小单位。一个二进制位只能表示0或1两个状态。
B通常指字节(Byte),它是计算机存储容量的单位,一个字节等于8个二进制位(bits)。
当我们需要描述一个文件的大小、网速带宽时,使用大写字母B表示,如1MB/s。而当我们用二进制数字表示数据长度,例如密码长度、编码表达式时,使用小写字母b来表示,如8位二进制数可以表示256种不同的数值组合,简写为8b。
3.位权、基数
位权:39 十位上、各位上相乘的数 10的一次幂,10的零次幂
基数:二级制的2 十进制的10
移位运算:二进制 左右移动
《貌似可以替代乘法或除法》
4.补数
二进制表示负数 高位是符号位 0是正数 1是负数
5.逻辑运算
NOT AND OR XOR(异或)
第3章 计算机进行小数运算时出错的原因
1.浮点数 (符号、尾数、基数、指数)
double 64位
float 32位
例子:
1001.011可以表示为:
符号位为0(正数)
尾数为1.001011
基数为2
指数为3
对应十进制数为9.375
2.在C语言中 0x表示十六进制
第4章 熟练使用有棱有角的内存
1.内存 IC 中有电源、地址信号、数据信号、控制信号等
2.内存的基本单位是字节(byte),一个字节等于8个比特(bit)
3.可以将内存想象成楼房,每一层是一个字节
在程序中 不同的数据类型 存储的大小有区别 对应着内存上 就是指定的字节数为单位
4.指针
指针是一种变量 存储数据的内存地址
5.数组是高效使用内存的基础
《1》内存连续性:数组中的元素在内存中是连续存储的,这使得 CPU 能够快速地读取和处理数组元素,提高了访问速度。
《2》数据类型相同:数组中的元素通常只包含同一种类型的数据,这种特性可以提高数据的紧凑性和操作效率。
《3》随机访问能力:数组允许随机访问,即可以通过索引值快速访问指定位置的元素,这比链表等数据结构更高效。
《4》可预测性:由于数组元素内存地址的连续性,程序可以预测下一个元素内存地址的位置,这样可以避免频繁的内存分配和释放,提高了程序的效率。
6.栈、队列以及环形缓冲区
《1》栈(Stack)线性数据结构,它具有后进先出(LIFO)的特点。栈通常只允许在头部进行插入和删除操作,即向栈顶添加元素或者从栈顶移除元素。栈可以用来实现递归、括号匹配等操作。
两个问题:
为什么栈通常只允许在头部进行插入和删除操作?
栈通常只允许在头部(也即栈顶)进行插入和删除操作,是因为这种方式可以保证栈的后进先出(LIFO)特性。当新元素被添加到栈中时,它会成为新的栈顶,因此下一个被弹出的元素就是它。与此相反,如果在栈底进行插入和删除操作,新加入的元素就不得不排队等待之前所有元素都被弹出才能使用,这将失去栈结构的优势,并且使得操作复杂度大大提高。另外,由于栈通常只含有固定数量的元素,因此一般情况下也不需要在中间位置进行插入或删除操作。因此,在实现栈的数据结构时,仅支持在顶部进行操作是一种最基本、最简单、最高效的方法。
括号匹配是什么?
括号匹配是一个常见的编程问题,它涉及到检查一个字符串中的括号是否正确匹配。在这个问题中,可以使用栈来实现算法。
具体操作是:从左到右遍历字符串中的每个字符,如果当前字符是左括号(例如“(”或“{”或“[”等),则将其推入栈中;如果当前字符是右括号(例如“)”或“}”或“]”等),则检查栈顶元素是否与之相匹配,如果匹配,则将栈顶元素弹出继续遍历;如果不匹配,则意味着字符串无效,并且可以立即返回错误。当所有字符都被遍历时,如果栈为空,则表示所有括号都已经得到匹配,字符串有效。否则,字符串无效,括号不匹配。
例如,对于字符串“{[]}”,该算法将按照以下方式检查括号匹配:
首先将“{”推入栈中。
然后将“[”推入栈中。
接下来,“]”与栈顶元素“[”匹配,将“[”弹出。
最后,“}”与栈顶元素“{”匹配,将“{”弹出。
遍历完成后,栈为空,表示所有括号都得到了匹配,字符串有效。
总结来说,括号匹配涉及到使用栈来检查括号的正确配对,它在编程中是一个有用而常见的问题。
《2》队列(Queue)是一种线性数据结构,它具有先进先出(FIFO)的特点。队列通常只允许在队首进行删除操作,而在队尾进行插入操作,即向队尾添加元素或者从队首移除元素。队列可以用来实现消息传递、BFS等算法。
《3》环形缓冲区(Circular buffer)是一种环形的、固定长度的缓冲区,它可以用于存储流式数据。环形缓冲区由一个固定长度的数组和两个指针组成,分别表示缓冲区的读和写位置。当读指针压上缓冲区边界时,会自动回到缓冲区的起始位置,也就是说,最后一个元素和第一个元素最为相邻。环形缓冲区常常被用于计算机网络中实现数据包的收发处理和循环队列。