6

我现在正在学习编程语言原理课程,但我一生都无法弄清楚这一点。这不是作业,只是一个一般概念问题。

在我们的课程中,我们讨论了静态链和显示。我想我明白为什么我们需要这些。否则当我们有嵌套方法时,当我们有嵌套方法时,我们无法弄清楚我们在谈论什么变量。

我的教授还谈到了符号表。我的问题是符号表是做什么用的?它与静态链有什么关系?

我会提供一些背景信息(如果我错了,请纠正我)。


(我将定义一些东西只是为了使解释更容易)

假设我们有这样的代码:

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 |
|--|                              --------------------------------------------------
|  |
|--|
  • 链接到下一个 - 如果多个事物具有相同的哈希值,则这是一个链接
  • name - 元素的名称(例如:i、j、a、int)
  • 类型 - 事物是什么(例如:变量、函数、参数)
  • 范围级别 - 不是 100% 确定这是如何定义的。我觉得:
    • 0 将是内置的
    • 1 将是全局变量
    • 2 将是主要方法
    • 3 将是 a 和 b
    • 4将是innerA

只是为了重申我的问题:

  • 符号表是干什么用的?
  • 它与静态链有什么关系?
  • 为什么我们需要静态链,因为范围信息在符号表中。
4

2 回答 2

5

请注意,“符号表”可以表示两种不同的含义:它可能表示编译器用于确定变量的哪个别名具有范围的内部结构,或者它可能表示库在加载时向其用户导出的符号列表时间。在这里,您使用的是前一个定义。

符号表用于确定用户在使用某个名称时所指的内存地址。当你说“x”时,你想要“x”的哪个别名?

您需要同时保留静态链和符号表的原因是:当编译器需要确定哪些变量在某个范围内可见时,它需要“取消屏蔽”先前在内部范围内别名的变量。例如,当从innerAback 移动到时a,变量i会更改其内存地址。同样的事情再次a发生main. 如果编译器没有保留静态链,则必须遍历整个符号表。如果你有很多名字,那就太贵了。对于静态链,编译器只查看当前级别,删除其中包含的每个变量的最后一个定义,然后沿着链接向上一个范围。另一方面,如果您没有符号表,那么每个不在本地范围内的变量访问都会使编译器不得不遍历静态链。

总结一下,可以从静态链重构符号表,反之亦然。但是您真的希望两者兼而有之,以加快常见情况的操作。如果缺少符号表,编译将花费更长的时间,因为每个非局部范围的变量访问都需要爬上静态链。如果您缺少静态链,则编译将花费更长的时间,因为离开作用域将需要遍历符号表以删除现已失效的条目。

顺便说一句,如果您还没有使用 Michael Scott 的Programming Language Pragmatics,您应该看看它。这是迄今为止我见过的关于这个主题的最好的教科书。

于 2010-08-02T18:18:25.393 回答
1

这显然是指一些特定的类实现,为了理解它,我强烈建议与与该类相关的人交谈。

符号表是将源代码标识符转换为编译器可以使用的东西。它保留了必要的描述。它倾向于在整个编译过程中使用。您提到的“类型”看起来像是用于解析,并且毫无疑问会有更多条目(在“其他”中)用于后期阶段。

很难知道它与静态链有何关系,或者为什么需要它们,因为您甚至不知道“范围级别”是什么。但是,请注意两者a()b()可能都有一个 variable i,您似乎认为它们具有相同的作用域级别,因此您需要一些东西来区分它们。

Also, the static chain is frequently an optimization, so the compiler knows which symbol table entries to accept. Without a static chain, the compiler would have to do some lookups to reject an entry in b for something encountered in innerA.

To get anything more useful, you're going to have to explain more about what's going on (I'd strongly suggest talking to the instructor or TAs or whatever) and probably have more specific questions.

于 2010-08-02T18:23:58.683 回答