符号表中存储了哪些信息?
编程语言将决定存储的大部分信息,但目标架构也会影响存储的数据。关于如何生成代码的一些假设会影响表中存储的值。
当考虑可以存储的关于标识符的信息范围时,根据标识符所代表的结构对标识符进行分类似乎是合乎逻辑的。换句话说,需要为常量、变量、过程、枚举和类型定义等存储不同的数据。
常数
常量是定义永远无法更改的永久值的标识符。由于程序员希望通过名称访问这些值,因此必须存储名称。
变量
变量是标识符,其值可能会在程序执行之间和单次执行期间发生变化。它们代表某个内存位置的内容。符号表需要在运行时记录变量名及其分配的存储空间。
类型(用户定义)
用户定义类型是一种或多种当前类型的混合。类型按名称创建并引用类型定义结构。每个结构都将记录关于它自己的重要信息,例如它的大小、其成员的名称或它的上限和下限。
子程序
过程、函数和方法是命名的代码段。自然地,符号表应该记录一个过程的名称。
应注意它们返回的类型(如果有)。在运行时访问子程序时,通常是通过它们在代码流中的位置(或该位置的某个句柄)。因此,还应记录为给定程序生成的代码的位置。
班级
类是抽象的,是一种限制对其成员访问的数据类型,封装提供了适当的语言级多态性。它们是用户定义类型的特例,在结构上没有区别。但是,存储有关类的信息可能会很方便,超出其他用户定义类型所需的信息。
遗产
有许多不同的方式来执行继承,需要一个符号表记录来跟踪哪些类正在被继承以及继承是如何执行的。在C++中,关键字public、private和protected修改了继承项的可见性,可以和继承信息一起记录。
数组
数组表示可以由索引随机访问的相似类型元素的集合。对于数组的每个维度,编译器都需要知道数组的下边界(最低子索引)、上边界(最宽子索引)、索引大小、索引类型、总大小等信息,以及所包含元素的类型。
记录
Records定义了一组可以通过名称创建的可能异构的成员。编译器还需要知道记录的大小(为所有成员分配多少空间)。
模块
它可以存储模块大小、名称、父级、成员和时间戳。时间戳用于在加载时保证模块已按正确顺序编译或都是最新的。