我现在正在学习编程语言课程的原则,但我不能为我的生活弄清楚这一点。这不仅仅是一个普通的概念问题。
在我们班上,我们讨论过静态链和显示。我想我理解为什么我们需要这些。否则,当我们有嵌套方法时,我们无法弄清楚当我们有嵌套方法时我们正在谈论的变量。
我的教授也谈到了一个符号表。我的问题是用于的符号表是什么?它与静态链有什么关系?
我会给出一些背景(如果我错了,请纠正我)。
(我将定义一些内容,以便更容易解释)
假设我们有这段代码:
main(){
int i;
int j;
int k;
a(){
int i;
int j;
innerA(){
int i = 5;
print(i);
print(j);
print(k);
}
}
b(){
...
}
...
}
这个堆栈:
| innerA |
| a |
| b |
| main |
-----------
静态链的快速描述作为复习。
静态链用于查找在内部函数内重新定义变量时应使用的变量。在上面显示的堆栈中,每个帧都有一个指向包含它的方法的指针。所以:
| innerA | \\ pointer to a
| a | \\ pointer to main
| b | \\ pointer to main
| main | \\ pointer to global variables
-----------
(假设静态作用域,对于动态作用域,我认为每个堆栈帧都只指向它下面的那个)
我认为当我们在print(<something>)
方法中执行innerA
时,会发生这种情况:
currentStackframe = innerAStackFrame;
while(true){
if(<something> is declared in currentStackFrame)
print(<something>);
break;
else{
currentStackFrame = currentStackFrame.containedIn();
}
}
快速复习符号表
我不确定符号表的用途。但这就是它的样子:
Index is has value,
Value is reference.
__
| |
|--| --------------------------------------------------
| | --------------------> | link to next | name | type | scope level | other |
|--| --------------------------------------------------
| | |
|--| ---------------
| | |
|--| | --------------------------------------------------
| | -------> | link to next | name | type | scope level | other |
|--| --------------------------------------------------
| |
|--|
重述我的问题:
答案 0 :(得分:5)
请注意,“符号表”可能意味着两个不同的东西:它可能意味着编译器用来确定变量的哪个别名具有范围的内部结构,或者它可能意味着库导出到其的符号列表用户在加载时。在这里,您使用的是前一个定义。
符号表用于确定用户使用某个名称时用户所指的内存地址。当你说“x”时,你想要“x”的别名吗?
您需要同时保留静态链和符号表的原因是:当编译器需要确定哪些变量在某个范围内可见时,它需要“取消屏蔽”先前在内部范围中别名的变量。例如,当从innerA
移回a
时,变量i
会更改其内存地址。从a
到main
再次发生同样的事情。如果编译器没有保留静态链,则必须遍历整个符号表。如果你有很多名字,那就太贵了。对于静态链,编译器只查看当前级别,删除其中包含的每个变量的最后一个定义,然后跟随一个范围的链接。另一方面,如果您没有符号表,那么不在本地范围内的每个变量访问都会使编译器必须遍历静态链。
总结一下,您可以从静态链重构符号表,反之亦然。但是你真的希望两者都能快速完成常见的操作。如果缺少符号表,则编译将花费更长时间,因为每个非本地范围的变量访问都需要爬上静态链。如果缺少静态链,则编译将花费更长时间,因为保留范围将需要遍历符号表以删除现在已解散的条目。
顺便说一下,如果你还没有使用Michael Scott的编程语言语用学,你应该看看它。到目前为止,这是我见过的关于这个主题的最好的教科书。
答案 1 :(得分:1)
这显然是指某些特定的类实现,为了理解它,我强烈建议与与该类相关的人交谈。
符号表将源代码标识符转换为编译器可以使用的内容。它保留了必要的描述。它往往在整个编译过程中使用。你提到的“类型”看起来像是用于解析,并且无疑会有更多的条目(在“其他”中)用于后期阶段。
很难知道它与静态链的关系,或者为什么需要它们,因为你甚至不知道“范围级别”是什么。但请注意,a()
和b()
可能都有变量i
,您似乎认为它们具有相同的范围级别,因此您需要一些区分它们。
此外,静态链通常是优化,因此编译器知道要接受哪些符号表条目。如果没有静态链,编译器必须进行一些查找以拒绝b
中innerA
中遇到的内容中的条目。
为了获得更多有用的东西,你将不得不更多地解释正在发生的事情(我强烈建议与教练或助教或其他人交谈)并且可能有更具体的问题。