0

我在静态/动态范围内遇到以下问题:

下面的程序片段是用允许全局变量但不允许函数嵌套声明的编程语言编写的。

 global int i = 100, j = 5; 
 void P(x) { 
  int i = 10; 
  print(x + 10); 
  i = 200; 
  j = 20; 
  print (x); 
 } 
 main() {P(i + j);} 

Q1。如果编程语言使用静态作用域和按需参数传递机制调用,上述程序打印的值是

(A) 115, 220 (B) 25, 220 (C) 25, 15 (D) 115, 105

Q2。如果编程语言使用动态作用域和按名称调用参数传递机制,则上述程序打印的值是

(A) 115, 220 (B) 25, 220 (C) 25, 15 (D) 115, 105

我的想法:

在 Q1:因为它是静态范围,并且根据需要调用,x 应该替换为 i + j。但这会导致本地名称冲突,因为已经有一个名为 i 的变量。所以它(全局 i)可能会被重命名,让我们说 i1,然后调用将是:

   first call: print(x+10) -> (i1 + j + 10) -> (100 + 5 + 10) -> 115
   second call: print(x) -> print(i1 + j) -> 105 (Already evaluated - call by need)

关于 Q2:在动态作用域中,您首先在本地函数中搜索变量,然后在调用本地函数的函数中搜索,然后在调用该函数的函数中搜索,依此类推,直到调用堆栈。

根据名称调用:

print (i1 + j + 10) -> print (100 + 5 +10 ) -> 115

第二个电话将是

print(x) -> print(i1 + j) -> (100 + 20) = 120 // Evaluate again - Call be name.

这个答案正确吗?(选项中不存在)我缺少什么吗?(可能是动态绑定?)

4

3 回答 3

4

第一季度

OP的答案是正确的(D)。事实上,由于 globali在执行过程中没有被修改,所以call by needcall by valueP没有区别。

这是一个确实有所作为的示例:

global int i = 100, j = 5;

void IncreaseTheGlobal() {
    i = i + 1;            // static scoping means this is the GLOBAL i!
    print(i);
}

void P(x) {
    int i = 10;
    IncreaseTheGlobal();  // 101 (increased global i)
    print(i);             //  10 (local i)
    print(x);             // 106 (x is evaluated; picks up increased global i)
    IncreaseTheGlobal();  // 102 (2nd time increased global i)
    print(x);             // 106 (x not re-evaluated; unaffected by 2nd increase)
}

main() {
    print(i);             // 100 (original global i)
    P(i + j);
    print(i);             // 102 (new global i)
}

正如 OP 已经指出的那样,第一次x被评估时,它会获取 globali在特定时刻具有的任何值。在初始评估之后,x不再受以后修改 global 的影响i

第二季度

按名称调用通常用于宏语言。那么为什么不使用最著名的宏语言:C 预处理器呢?

#include <stdio.h>

int i = 100, j = 5;

#define print(num)  printf("%d\n", num)

#define P(x) {     \
    int i = 10;    \
    print(x + 10); \
    i = 200;       \
    j = 20;        \
    print(x);      \
}

main() {
    P(i + j);
}

编译,运行,查看:25、220。

按名称调用与简单的搜索和替换一起使用;在的体内P,替换每一个出现的xby i + j

int i = 10; 
print(i + j + 10);    // 10 + 5 + 10 = 25
i = 200;
j = 20;
print(i + j);         // 200 + 20 = 220

换句话说, theijinsidei + j只是在评估时获取恰好在范围内的任何内容的现值x

所以正确答案是B,对吧?好吧,几乎……正确答案取决于print. 假设print实践也按名称调用 print定义了自己的局部变量i,那么这将极大地改变结果。尝试这个:

#define print(num)  { int i = 0; printf("%d\n", num); }

结果现在更改为 15、20。

这可能是动态作用域对代码的可维护性不利的最重要原因。函数的实现更改print(即使是像更改局部变量的名称这样微不足道的事情)可能会在更高级别上破坏函数。

于 2014-02-02T12:28:56.053 回答
0

In the second part that is Call by name

The line i=200 will update the local i

Now while print(x) is called it will be replaced by print(i+j)=>print(200+20)=>220

于 2013-02-08T15:49:12.377 回答
0

对于第一季度:

int i = 10; 
print(x + 10); // print (i + j + 10); prints 10 + 5 + 10 = 25; local i gets used here

i = 200; 
j = 20; 

print (x); // print (i + j); call by need ensures, no reevaluation and i + j is 15. 

所以,答案是 C - 25, 15

于 2015-04-22T22:35:07.160 回答