創作內容

3 GP

Call by value, Call by reference (address), Call by name, Call by value and copy restore

作者:GJLMoTea│2018-07-09 18:00:56│巴幣:1,012│人氣:2652

程式傳遞參數的方法有很多種,
近代程式語言常用的只有call by value call by reference(address) 兩種
call by name copy restore 則見於早期程式語言



先來舉個例子


在以下程式碼,
Call by value
Call by reference (or Call by address)
Call by name
Call by value and copy restore
四個各別會印(print)出什麼結果呢?


1   Program Test:           
2   begin                       
3     x=1;                
4     y=2;             
5     SUB(x,x+y);          
6     print(x);            
7   end;               
8                    
9                    
10   Program SUB(i,j):         
11   begin                
12     i=i+1;           
13     print(x);          
14     i=i+j;             
15     print(i);            
16   end;              






(做成圖片的樣子)








Answer 不同call by的答案
Call by value:1,5,1
Call by reference (or Call by address):2,5,5
Call by name:2,6,6
Call by value and copy restore:1,5,5

Call by value 和 Call by reference 還蠻好理解的,但我以前一直搞不懂Call by name為什麼是這個結果,以下來一一解釋






Call by value:
        5行   SUB(x,y)是傳value SUB(1,3)進去副程式,副程式裡的i,j為1,3,
       12行    接著i=i+1   加完後此時i=2
       13行    print(x)  x數值是第3行宣告的1,於是第一個印出來的是1。
       14行    i=i+j  也就是i=2+3 加完後i=5
       15行    print(i),於是第二個印出來是5。
      副程式跑完回到主程式
        6行     print(x),x的數值從頭到尾都沒有動過,x數值仍是第3行宣告的1,於是第三個印出來的是1








Call by reference (Call by address):
        5行     SUB(x,y)是傳x,y的參考(address)  SUB(x,y)進去副程式,副程式裡的i,j跟x,y是命運相連體 為1,3,x等於i,y等於j
      在副程式裡對i (x address), j (y address)做操作 等於是對x,y變數做操作,副程式參數會影響主程式
       12行    接著i=i+1   加完後此時i=2 (也就是x=2)
       13行    print(x)  x數值是2,第一個印出來的是2
       14行    i=i+j  也就是i=2+3 加完後i=5(也就是x=5)
       15行    print(i),於是第二個印出來是5。
      副程式跑完回到主程式
        6行     print(x),x數值是第14行跑出來的5,於是第三個印出來的是5







Call by name:
        5行     SUB(x,y)是傳x,y的變數名稱,把SUB(i,j) 替換成 SUB(x,x+y)進去副程式,副程式裡的(i,j)被取代成(x,x+y)
      於是在副程式看到 i 就等於看到 x 看到 j 就等於看到 x+y
       12行    接著i=i+1   =>x=x+1加完後x=2
       13行    print(x)  x數值是2,第一個印出來的是2
       14行    i=i+j  =>  x = x + (x+y)  =>  x=2+(2+2)    加完後 x=6
       15行    print(i)   =>   print(x),於是第二個印出來是6。
      副程式跑完回到主程式
       6行     print(x),x數值是第14行跑出來的6,於是第三個印出來的是6

      call by name 的設計傳參數時 偶爾會產生Bug,例如 當 SUB(x+y , x) 時,
      會發生第12行 i = i+1  =>  x+y = x+y +1的情況









Call by value and copy restore:
和Call by value很像,只差在於 離開副程式function時 會把變數值存回位址
        5行     SUB(x,y)是傳value SUB(1,3)進去副程式,副程式裡的i,j為1,3,
       12行    接著i=i+1   加完後此時i=2
       13行    print(x)  x數值是第3行宣告的1(因為此時還未離開副程式,沒有把值存回x變數的位址),於是第一個印出來的是1。
       14行    i=i+j  也就是i=2+3 加完後i=5
       15行    print(i),於是第二個印出來是5。
      副程式跑完回到主程式 離開副程式,把 i 值(5)存回 x 位址
        6行     print(x),x數值仍是離開副程式存回的 5,於是第三個印出來的是5



引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4051523
All rights reserved. 版權所有,保留一切權利

相關創作

留言共 2 篇留言

Shark
範例要補充一個地方:x,y是全域變數,否則第13行有「x未定義」的錯誤。

延遲求值(lazy evaluation)的語言基本上都是call by name。
我想call by name因為難以預料會發生什麼事,如上面的例子,所以較新的程式語言都不採用了。
不過腳本語言大多有函式能把字串視為程式碼解譯並執行,可以模擬call by name。
像Python可以這樣寫

x=1

def testFunc(expression, y):
  global x
  x=eval(expression)
  print('x=%d y=%d' % (x,y))

exp="x+y"
testFunc(exp,1) #印出x=2 y=1
testFunc(exp,1) #印出x=3 y=1
testFunc(exp,3) #印出x=6 y=3

另外在巴哈姆特發文時,切換到原始碼像這樣打,就可以做到背景是黑色,字型是等寬字型。

[div bgcolor=#000000][font=Courier New]
在這裡打程式碼
[/font][/div]

07-10 06:46

GJLMoTea
感謝建議07-11 00:08
老皮
有點久了,
但想請問你寫的call by reference 直接傳x的位址給i 跟y 的位址給j
但不是應該要傳x+y的位址給j嗎(因為範例給SUB(x, x+y))

如果是我說的傳x+y的位址給j是不是就不會對原本的y值造成影響

12-21 17:59

我要留言提醒:您尚未登入,請先登入再留言

3喜歡★GJLMoTea 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:Lex Yacc LLV... 後一篇:撲克牌玩法:排七...

追蹤私訊切換新版閱覽

作品資料夾

chanxin95107所有老師們
翻譯菜鳥一枚,放了些蔚藍檔案的翻譯作品在小屋裡,有興趣的歡迎挑看選看( • ̀ω•́ )✧看更多我要大聲說昨天11:18


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】