《编译原理学习笔记》

只是摘抄了一些个人认为比较重要的,常常和我们编写程序时容易相关的一些内容。

  1. 预处理器:把源程序聚合在一起,同时负责宏替换
  2. 编译器:接收预处理的输出作为输入,然后进行处理,输出汇编程序
  3. 汇编器:将汇编程序进行处理,生成可重定位的机器代码
  4. 链接器:解决外部内存的地址问题(大型程序经常被分为多个部分进行编译,因此,可重定位的激起代码有必要和其他可重定位的目标文件和库文件连接到一起,形成真正在机器上运行的代码。一个文件中的代码可能指向另一个文件中的位置)
  5. 加载器:把所有的可执行目标文件放到内存中进行执行

一个语言处理系统如下:

《编译原理学习笔记》_第1张图片

一个编译器的各个步骤:

《编译原理学习笔记》_第2张图片

 

符号表:是一种公编译器用于保存有关源程序构造的各种信息的数据结构。这些信息在编译器的分析阶段被逐步受击并放入符号表,它们在综合阶段用于生成目标代码。符号表的每个条目包含一个与表示服相关的信息,比如它的字符串(或者词素)、它的类型、它的存储位置和其他相关信息。符号表通常需要支持同一标识符在一个程序的多重声明

我们将为每个作用域建立一个单独的符号表来实现其作用域。每个带有声明的程序块都会有自己的符号表,这个块中的每个声明都在此符号表中有一个对应的条目。这种方法能对其他能够设立作用域的程序设计语言构造同样有效。例如:每个类也可以有自己的符号表,它的每个域和方法都在此表中有一个对应的条目。

符号表条目是在分析阶段由词法分析器、语法分析器和语义分析器创建并使用的。一个符号表的作用是将信息从声明的地方传递到实际使用的地方。

符号表管理:编译器重要的功能之一就是记录源程序中使用的变量的名字,宁手机和每个名字的各种属性有关的信息。这些属性可以提供一个名字的存储分配、它的类型、作用域(即在程序哪些地方可以使用这个名字的值)等信息。对于过程名字,这个信息还包括:它的参数变量和类型分、每个参数的传递方法(如值传递和引用传递)以及返回类型。符号表数据结构为每个变量名字创建了一个记录条目,记录的字段各个属性。这个数据结构应该允许编译器迅速查找到每个名字的记录,并向记录中快速存放和获取记录中的数据。后面会详细讨论符号表。

 

二进制翻译:编译技术可以用于把一个机制的二进制代码翻译成另一个机器的二进制代码,使得可以在一个机器上运行原本为另一个指令集编译的程序。二进制翻译技术已经被不同的计算机公司用来增加他们的机器上的可用软件。

 

生明和定义的区别:声明告诉我们事物的类型,定义告诉我们它们的值

值传递:在值传递中,会对实在参数求值(如果它是表达式)或者拷贝(如果它是变量)。这些值被放在属于调用过程的相应形式参数的内存位置上。其效果是:被调用过程中所做的所有有关形式参数的计算都局限于这个过程(即函数),相应的实在参数本身不会改变。

引用传递:在引用调用中,实参的地址作为相应的形式参数传递给被调用者。在被调用的代码中使用形参时,实现方法是沿着这个指针找到调用者指明的内存位置。因此,对形参的改变操作就是在改变实参。当形参是一个大型的对象、数组或者结构时,引用传参是必不可少的

 

一个语法编译器前端的模型:

《编译原理学习笔记》_第3张图片

局部变量名的存储布局:从变量的类型我们可以知道该变量在运行的时刻需要的内存数量。在编译时刻,我们可以使用这些数量为每个名字分配一个相对地址。名字的类型和相对地址信息保存在相应的符号表条目中。对于字符串这样的变长数据以及动态数组这样的只有在运行时才能确定其大小的数据类型,处理的方法是为指向这些数据的指针保留一个一直固定大小的存储区域。运行时刻的存储问题将在后面进行讨论。

注意地址对齐问题。因为字节对齐的原因而产生的闲置空间称为补白。

多字节数据对象往往被存储在一段连续的字节中,并以初始字节的地址作为该对象的地址。

从编译器的角度来看,正在执行的目标程序在它自己的逻辑地址空间内运行,其中每个程序值都在这个虚拟地址空间中有一个地址。对这个逻辑地址的管理和组织是由编译器、操作系统和目标机共同完成的。操作系统将逻辑地址映射为物理地址,而物理地址对整个内存空间编址。

生成的目标代码的大小在编译时刻就固定下来勒 ,因此编译器可以将可执行目标代码放在一个静态确定的区域:代码区。

不能被引用的数据通常称为垃圾。垃圾回收的目的是为了重新收回那些存放了不能再被程序访问的对象的存储块。

不是所有的语言都适合进行垃圾自动回收。为了能使垃圾回收器能正常工作,它必须知道任何给定的数据元素或一个数据元素的分量是否为(或可否被用作)一个指向某块已分配存储空间的指针。在一种中语言中,如果任何数据分量的类型都是可确定的,那么这种语言就被称为类型安全的。对于某些类型安全的语言,我们可以在编译时刻确定数据的类型。另外一些类型安全的语言(比如Java),其类型不能再编译时刻确定,但是可以在运行时刻确定。后者称为动态类型安全语言。如果一个语言既不是类型安全的也不是动态类型安全的,它就被称为不安全的

类型不安全的语言不适合使用自动垃圾回收机制,比如C和C++。在不安全语言中,存储地址可以进行任意操作:可以将任意的算术运算符应用于指针,创建出一个新的指针,并且任何证书都可以被强制转化为指针。因此,从理论上来说,一个程序可以在任何时候引用内存中的任何位置。这样,没有哪个内存位置可以被认为是不可访问的,也就无法安全的回收任何存储空间

《编译原理学习笔记》_第4张图片

编译时刻能确定大小的区域:目标代码的大小(即代码区)、静态数据区(存放全局常量和编译器生成的其他数据)

编译期间不能确定大小的区域:堆区和栈区(在运行时刻确定)

栈区存放的是过程的活动记录,活动记录会随着过程的调用和返回被创建和消除。活动记录的大小和布局是由代码生成器通过存放于符号表中的名字信息来确定的

虚拟机是一些字节代码中间语言的解释程序,这些字节代码是为诸如Java和C#这样的语言生成的

 

你可能感兴趣的:(C++学习)