说明网址: http://libai.math.ncu.edu.tw/bcc16/C/C/b14.shtml
-------------------------------------------------------------------------------
其實 call-by-name 並不等於 call-by-reference。call-by-name 源自於 Algol60 這個
call-by-name 被定義為 Name Replacement:「參數列中的每個參數,如果未指定以
傳值的方式來傳遞,就必須以實際傳入的參數來取代。」在 Compilers - Principles,
Techniques, and Tools 這本書的 7.5 節中,它被解釋為 inline-expansion。其原因
是,以 call-by-name 的方式呼叫函式時,如果在某個參數位置上指定了一個運算式
(expression) 當作參數,那麼這個 expression 會被直接傳入函式裡面進行展開,所以,
這個 expression 是在函式裡面才進行運算的,而不是在參數列中預先計算好它的值再傳
進去。這就產生了 delayed evaluation (延遲計算) 的效果。delayed evaluation 的好處
是,只有當函式需要某個 expression 參數的值,該 expression 才會被計算,否則就不
用了。call-by-name 比較顯著的例子是 swap 函式,swap 通常是這樣寫的:
proc swap(A, B) {
tmp = A;
A = B;
B = tmp;
}
proc main() {
i = 2;
a[3] = {5, 6, 7};
swap(i, a[i]);
}
swap 的實際工作情形是:
swap(i, a[i]) { // i is 2
tmp = i; // tmp becomes 2, since i is 2
i = a[i]; // i becomes 7, since a[2] is 7
a[i] = i; // inline expansion of B, delayed evaluation ==> a[7] = 7
}
在 P(X, Y, Z) 這個例子中:
proc P(X, Y, Z) {
Y = Y + 1;
Z = Z + X;
}
P(a+b, a, a) { // a = 2, b = 3
a = a + 1; // a becomes 3
a = a + (a+b); // inline expansion of X, a becomes 9
}
----------------------------------------------------------
您提供的參考網址中有一句話, 或許可以拿來這邊做解釋
「在計算機裡面,一個變數的位址,才是它真正的名字。」
也就是說, call-by-name 的意義等同於call-by-address
只是 call-by-address 是直接給了人類無法直接理解的位址
call-by-name 則是給了人類可以直接理解的代號(ex:test[]的 "test")
大概是這樣子吧?@@a...
我是看了您給的參考網址得出這樣的結論, 現學現賣:p
----------------------------------------------------------
链接:http://jpkc.nwpu.edu.cn/jp2005/20/kcwz/zdnd/z5.html
7.过程说明和过程调用
过程说明的翻译主要完成如下工作:
(1)填写符号表将过程的相关信息填写到表中,由于过程名不同于其他变量名,往往需使用“过程信息向量”记录其入口地址、各参数信息;
(2)产生将调用点地址压入栈的代码;
(3)产生形、实参结合的代码;
(4)产生过程体的翻译代码;
(5)产生返回调用点的代码。
实现过程说明和调用还应解决实参与形参间的信息传递(简称形实结合)的方式问题。常见的形实结合方式有引用调用、值调用、结果调用、值结果调用以及名字调用等等:
⑴引用调用(Call by reference)这种方式是在过程调用的代码序列中给出实参的地址(如果实参是简单变量或下标变量,则在调用代码序列中直接给出其地址;显然,按此种方式实现形实结合,执行过程时,对形参的赋值将会影响相应实参之值(右值)。
⑵值调用(Call by value)值调用也是一种经常采用的方式(PASCAL语言中的值参、C语言中的所有参数等等)。结合方式是,送入形式单元的不是相应实参的地址而是它的值。在执行过程体期间,除了以实参之(右)值作为形参的初值进行运算之外,将不再与实参发生任何联系。
⑶结果调用(Call by result)和值结果调用(Call by value-result)其特点是,为每个形参分配两个形式单元,第一单元用于存放实参的地址(左值),第二单元用于存放实参的(右)值(在结果调用中,实参的值将不被传送),在执行过程体时,将只对第二单元进行操作,但在返回时,将第二单元的内容,按相应的第一单元中的地址传给实参。
⑷名字调用(换名调用Call by name)在早期的ALGOL语言中使用,其原理是,将形参视为过程体中的一个宏,形实结合时,将形参在过程体的每个出现,均用实参表达式取而代之,为避免引起运算顺序变化,结合时将自动为实参表达式加上括号。
对于过程调用语句的翻译,要点是:
(1)翻译计算各实参表达式的代码,并将此代码段入口放入队列;
(2)将计算实参表达式的入口队列翻译为入口参数四元式
(par,0,0,Ai)
(3)生成转向过程子程序的四元式(call ,0,0,P)
------------------------------------------------------------------------------------------------------------------
东南大学编译原理网络课堂52讲里对call by name的解释
传名过程调用相当于把被调用段的过程代替调用语句,并且过程体内形参名皆用相应的实参名代替