我遇到了静态/动态范围的以下问题:
以下程序片段是用允许全局的编程语言编写的 变量并不允许嵌套的函数声明。
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)
On Q2:在动态作用域中,首先在本地函数中搜索变量,然后在调用本地函数的函数中搜索,然后在调用该函数的函数中搜索,依此类推,向上调用堆栈。
按姓名呼叫:
print (i1 + j + 10) -> print (100 + 5 +10 ) -> 115
第二个电话将是
print(x) -> print(i1 + j) -> (100 + 20) = 120 // Evaluate again - Call be name.
这个答案是否正确? (不在选项中) 有什么我想念的吗? (动态绑定可能是?)
答案 0 :(得分:3)
OP的答案是正确的(D)。实际上,由于在执行i
期间未修改全局P
,因此按需调用和按值调用之间没有区别。
以下是 有所作为的示例:
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
时,它会获取全局i
在该特定时刻所具有的任何值。在初步评估之后,x
不再受以后修改全局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
的正文中,将x
的每一次出现都替换为i + j
。
int i = 10;
print(i + j + 10); // 10 + 5 + 10 = 25
i = 200;
j = 20;
print(i + j); // 200 + 20 = 220
换句话说,i
和j
里面的i + j
只是在评估x
时获取范围内的任何内容的现值。
所以正确答案是B,对吗?好吧,差不多......正确的答案取决于print
的实施。
假设print
实践按姓名调用,和 print
定义了自己的局部变量i
,那么这会大大改变结果。试试这个:
#define print(num) { int i = 0; printf("%d\n", num); }
结果现在变为15,20。
这可能是动态作用域对代码可维护性不利的最重要原因。函数print
中的实现更改(即使更改局部变量的名称也是微不足道的)可能会破坏更高级别的函数。
答案 1 :(得分:0)
在第二部分是按名称呼叫
i = 200行将更新本地i
现在,当print(x)被调用时,它将被print(i + j)=&gt; print(200 + 20)=&gt; 220
取代答案 2 :(得分:0)
对于Q1:
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