390 likes | 639 Vues
第七章 參數的傳遞. 陳維魁 博士 wkchen@pchome.com.tw 儒林圖書公司. 大綱. 副程式概念介紹 副程式基本觀念 參數傳遞的方法 別名 超荷法 通用性函數 六種常見的副程式呼叫方式 精選習題. 副程式概念介紹. 副程式的元素 副程式的名稱 參數 實際參數 (actual parameter) 呼叫副程式的參數串列即稱為實際參數,又稱為真實參數。 型式參數 (formal parameter) 被呼叫副程式的參數串列即稱為型式參數,又稱為虛擬參數 (dummy parameter). 副程式概念介紹. 副程式的元素
E N D
第七章 參數的傳遞 陳維魁 博士 wkchen@pchome.com.tw 儒林圖書公司
大綱 • 副程式概念介紹 • 副程式基本觀念 • 參數傳遞的方法 • 別名 • 超荷法 • 通用性函數 • 六種常見的副程式呼叫方式 • 精選習題
副程式概念介紹 • 副程式的元素 • 副程式的名稱 • 參數 • 實際參數(actual parameter) • 呼叫副程式的參數串列即稱為實際參數,又稱為真實參數。 • 型式參數(formal parameter) • 被呼叫副程式的參數串列即稱為型式參數,又稱為虛擬參數(dummy parameter)
副程式概念介紹 • 副程式的元素 • 環境(environment) • 由副程式執行時所參考的全域變數(global variable),區域變數(local variable)及其他必要的資訊構成 • 副程式執行的程式段
program demo;vara1,a2 : integer;....procedure swap(b1, b2:integer); vartemp: integer; begintemp := b1;b1 := b2;b2 := temp end;beginswap(a1, a2)end. 左例中swap(a1,a2)的參數串列(a1,a2)即為實際參數串列,副程式swap(b1,b2)中的參數串列(b1,b2)則為型式參數串列 範例
型式參數的語意模型 • 型式參數的三種不同語意模型分別為 • in mode • 型式參數可從對應的實際參數接收訊息。 • out mode • 型式參數可將訊息傳給對應的實際參數 • in out mode • 型式參數可從對應的實際參數接收訊息也可將訊息傳給對應的實際參數
實際與型式參數的對應關係 • 關鍵字對應法 • 參數的個數較多時適用 • 當參數的數目很多時,採用關鍵字對應法,程式的可讀性較高、較易維護不易出錯且可以不必按照特定順序 • 位置對應法 • 參數的個數較少時適用(通常是5個以下)
副程式的執行模式 • 副程式的執行動作是因為呼叫程式呼叫了副程式所引起 • 當呼叫程式呼叫副程式時會將程式的控制流程轉移到副程式開始處 • 待副程式執行結束時會將程式的控制流程轉移到呼叫程式中呼叫副程式敘述的下一個敘述 • 副程式執行時可改變其所處的環境的狀態
副程式的執行模式 呼叫程式執行 呼叫sub( )副程式 控制流程轉移到sub( )副程式 sub( )副程式執行 sub( )副程式執行完畢,控制流程轉移回呼叫程式 呼叫程式繼續執行
副程式的種類 • 程序(procedure) • 沒有傳回值 • 函式(function) • 函式與程序類似,最大的不同之處是函式會傳回一個值 • 函式本身亦具有型態 • 函式也可作為運算式的一部分
Pascal function gcd(a, b: integer):integer;begin if b = 0 then gcd := a else gcd := gcd(b, a mod b)end; 求最大公因數 程式段
求最大公因數 程式段 • Cint gcd(a, b)int a, b;{ if (b = = 0) return (a); else return (gcd(b, a%b));}
參數傳遞的方法 • 常見參數傳遞的方法 • 傳值呼叫法 • 傳址呼叫法 • 傳名呼叫法 • 數值結果呼叫法 • 本文呼叫法
傳值呼叫法 (call by value) • 呼叫程式呼叫被呼叫程式時,將呼叫程式中實際參數的值,傳給被呼叫程式中對應的型式參數 • 實際參數與相對應的型式參數不會佔用相同的記憶體空間 • 沒有副作用(side effect) • 只提供 in mode 參數
傳值呼叫法 (call by value) • 優點 • 實際參數的值只能被讀取,在副程式執行的過程中不會因為更改型式參數的值連帶地將實際參數的值更改 • 缺點 • 需配置額外的記憶體空間給型式參數使用
傳址呼叫法(call by address) • 又稱為call by reference或call by location • 呼叫程式呼叫被呼叫程式時,將呼叫程式中實際參數的位址,傳給被呼叫程式中對應的型式參數 • 實際參數與對應的型式參數會佔用相同的記憶體空間 • 有副效應 • 提供 in out mode 參數
傳址呼叫法(call by address) • 優點 • 不需配置額外的記憶體空間給型式參數使用 • 缺點 • 在副程式執行的過程中會因為更改型式參數的值連帶地將實際參數的值更改(副作用)
傳名呼叫法(call by name) • 呼叫程式呼叫被呼叫程式時,將呼叫程式中實際參數的名稱,傳給被呼叫程式中對應的型式參數 • 將副程式中所有型式參數的名稱以實際參數的名稱來替代 • 實際參數與對應的型式參數會佔用相同的記憶體空間
傳名呼叫法(call by name) • 優點 • 具有較大的彈性,可提供不同型式的實際參數讓同一個副程式做不同的工作 • 當實際參數為簡單變數時,傳名呼叫法之處理方式與傳址呼叫法相同 • 當實際參數為常數時,傳名呼叫法之處理方式與傳值呼叫法類似 • 缺點 • 程式難讀、不易製作、執行速度較慢及不易學習
數值結果呼叫法(call by value result) • 呼叫程式呼叫被呼叫程式時,將呼叫程式中實際參數的值,傳給被呼叫程式中對應的型式參數 • 實際參數與型式參數不會佔用相同的記憶體位置 • 當被呼叫程式執行完畢時,會將被呼叫程式中型式參數的值,傳回給呼叫程式中對應的實際參數 • 提供 in out mode 參數
設有一程式語言的副程式如下: PROCEDURE P(A,B,C); B=C; RETURN(A+C);END; 若X=1,Y=2,試問執行"R←P(X,X,X+Y)"之後對於 (a)傳名呼叫法 (b)傳值呼叫法 (c)傳址呼叫法三種不同的參數傳送的方式,R之值各為若干? 範例
若右例以: (a)傳名呼叫法 (b)傳值呼叫法 (c)傳址呼叫法 (d)數值結果呼叫法 四種不同的引數傳送的方式,A之值各為若干? procedure P(X,Y,Z); begin Y:=Y+1; Z:=X+X; end; begin A:=1; B:=1; P(A+B,A,A); print A; end. 範例
本文呼叫法(call by text) • 在呼叫時不把實際參數閉合(closure),而是一直延遲到遇到型式參數時再予閉合 • 用被呼叫程序環境閉合時的狀態計算實際參數之值 • “閉合”是指一程序與其相關環境繫結在一起之過程 • LISP之FEXPR版本採用此法
var x : integer;procedure text(y); var x : integer; begin x := 5; writeln(y); end;begin x:=4; text(x);end. 本文呼叫法處理結果為 5 傳名呼叫法處理則結果為 4 本文呼叫法範例
別名(aliasing) • 兩個或兩個以上名稱不同的變數,佔用相同的記憶體空間 • 別名形成的原因 • 參數傳遞時採用傳址呼叫法 • 變異記錄(variant record) • 指標 • Fortran的“equivalence”敘述
別名 現象對程式執行結果的影響 • 已知某一算術運算式(arithmetic expression):A×FUN(A)+A 若執行此運算式前之A值為2,FUN(A)傳回值為3,而執行此運算式時由於副作用(Side effect)造成A值變成6,則下列何者不可能是此運算式執行後之值? (A) 20 (B) 24 (C) 12 (D) 10
超荷法 (overloading) • 如果結構(constructure),因為引數的型態不同而具有不同的意義的話,則稱此現象為超荷法 • 範例 • A+B • 若A,B為整數則執行整數加法運算;若A,B為實數則執行實數加法運算 • Algol68中關於ABS()函數 • C++
通用性函數(generic function) • 允許參數傳遞的對象為“型態” • 主要的用途是可排除程序對資料型態的依賴性 • 優點 • 可減少程式碼的長度 • 可減少撰寫程式時,發生錯誤的可能性 • 代表性的語言是ADA
ADA 通用性函數範例 • generic type T is private;package P is procedure SWAP (A, B: in out T);end P;package body P is procedure SWAP (A, B: in out T) is temp : T; begin temp := A; A := B; B := temp; end;end P;
ADA 通用性函數範例 • procedure SWAPINT is new SWAP (integer); procedure SWAPINT(A,B:in out integer) istemp : integer; begintemp:=A;A:=B;B:=temp;end;
ADA 通用性函數範例 • procedure SWAPINT is new SWAP (real); procedure SWAPINT(A,B:in out real) istemp : real; begintemp:=A;A:=B;B:=temp;end;
六種常見的副程式呼叫方式 • 呼叫∕返回副程式(call∕return subroutine) • 遞迴副程式(recursive subroutine) • 例外處理副程式(exception handling subroutine) • 並行常式(coroutine) • 排程副程式(scheduled subroutine) • 並行程序(concurrent subroutine)
呼叫∕返回副程式 • 與一般的副程式呼叫是相同的 • 傳統的呼叫/返回副程式須滿足以下五項限制 • 不允許遞迴呼叫 • 副程式被呼叫時,必須有明顯的呼叫敘述 • 副程式被呼叫時,應從頭開始執行 • 副程式被呼叫時,控制流程應立即轉移 • 單一執行順序
遞迴副程式 • 若副程式可以呼叫本身或透過其他的副程式來呼叫本身 • 直接遞迴 • 副程式可以自己呼叫自己 • 間接遞迴 • 副程式可以透過其他的副程式來呼叫自己
例外處理副程式 • 處理例外情況的副程式 • 首創例外處理的語言為 PL/1
一種交換關係 假設有二個程序分別是P與Q,其中程序P可以啟動Q的執行,而程序Q也可以啟動程序P的執行 當程序啟動另一程序的執行時,會先將自己目前的狀態儲存起來,下次被啟動執行時,會由上次執行結束之處繼續往下執行,而非從頭開始執行 並行常式
排程副程式 • 一般的副程式呼叫是在被呼叫時,立即執行副程式 • 排程副程式在被呼叫時,並未立即被執行而是須在符合某種條件下才會被啟動執行 • 範例 • CALL SUB AT TIME=100 • 代表當時間為100時,副程式SUB才會被啟動。 • CALL SUB1 AFTER SUB2 • 代表當副程式SUB2執行完畢後,副程式SUB1才會被啟動
並行程序 • 同時執行的程式段即稱為並行程序
精選習題 • 傳名呼叫法、傳值呼叫法及傳址呼叫法在資訊定址值方面有早晚之分,試列出早晚的順序。 • 試問在JAVA語言中,函數之間的參數如何傳遞? • 簡釋傳值呼叫法與傳址呼叫法,並舉例說明何種狀況二者可得相同的結果,在何種狀況下二者所得不同。 • 在何種情況之下,傳址呼叫法和傳值結果呼叫法會得到不同的結果? • 在何種情況下,傳名呼叫法和本文呼叫法會得到不同的結果。