2013-02-06 49 views
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) Q2,105,

, , ,

。如果編程語言使用動態範圍界定並通過名稱 參數傳遞機制調用,通過上述程序 印刷的值是

(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. 

這是答案正確嗎? (不存在的選項) 有什麼我失蹤? (動態綁定可以是?)

+0

你摸不着頭腦?我被困在同樣的問題! –

回答

2

Q1

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的後期修改影響。

Q2

打電話名在宏語言通常使用。那麼爲什麼不使用最有名的宏語言: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的主體內,用i + j替換每個出現的x

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

換言之,該ij內部i + j只需拿起的任何恰好是在範圍時x被評估的當前值。

所以正確答案是B,對嗎?那麼,幾乎...正確的答案取決於print的實施。 假設print做法通過名稱呼叫print定義了自己的本地變量i,那麼這將大大改變結果。試試這個:

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

結果現在改變爲15,20

這可能是最重要的原因動態範圍界定不利於你的代碼的可維護性。函數print中的實現更改(即使更改局部變量的名稱也很簡單)可能會破壞更高級別的函數。

+0

對不起,我錯誤地認爲Q1是通過value_關於_call的;我做了一個編輯,使我的回答覆蓋了need_主題的_call。 –

+1

很好的解釋!我儘可能努力地投票! –

0

在第二部分即由名字呼叫

線路I = 200將更新本地I

現在的同時進行打印(x)被調用時,它將被替換通過打印(I + J)=>打印(200 + 20)=> 220

0

對於Q1: int i = 10; print(x + 10); // print(i + j + 10);打印10 + 5 + 10 = 25;當地我在這裏使用

i = 200;

j = 20;

print(x); // print(i + j);通過調用需要確保,沒有重新評估且i + j是15

所以,答案是C - 25,15