在程式設計中，引數又稱形式引數，是一種在呼叫子程式時用以向子程式傳遞資料的特殊變數，這些被傳遞資料也就是子程式引數的值。引數的有序列表通常包含在子例程的定義中，因此在每次呼叫子例程時也會計算這些傳入的引數，並且將對應資料送到子程式中。 不同於在數學中通常所使用的引數，電腦科學中的引數是在引動過程或者呼叫陳述式中傳遞給函式、程式或者常式的實際輸入表示式，而引數是子程式實現內部的變數。例如，定義一個 add 子程式為 def add x y return x y 那麼 xy 就是一對引數。當呼叫這個子程式時，例如 add 2 3 那麼，23 就是一對引數，請注意，呼叫上下文中的變數（及其表示式）可以是引數，如果以子程式的形式呼叫 a 2 b 3 add a b 則變數 a b 是引數，而不是值 2 3。 在最常見的傳值呼叫情況下，引數會在子程式中充當新的區域性變數，並初始化為引數的值（如果引數是變數，則為引數的區域性（隔離）副本）。但在例如傳引用呼叫的其他情況下，呼叫者提供的引數變數可能會受到被呼叫子例程中操作的影響。 所使用的語言一般定義瞭如何宣告引數以及將引數（的值）傳遞給子例程的引數的語義，但是在任何特定計算機系統中如何表示該引數的細節取決於該系統的呼叫約定。 示例 以下使用 C 語言編寫的程式定義了一個名為 SalesTax 的函式，並具有一個名為 price 的引數。price 的型別是 double，也就是雙精度浮點數。該函式的返回型別也是 double。 double SalesTax double pricereturn 005 price 定義函式後，可以按以下方式呼叫它： SalesTax 1000 示例中使用了引數 1000 呼叫該函式，此時值 1000 就會分配給 price，然後該函式開始計算其結果。產生結果的步驟在下面指定，並用 括起來。005 price 表示要做的第一件事是將價格乘以 005，即得出 050。return 表示函式將產生的結果 005 price 返回。因此，最終結果（忽略將小數部分表示為二進位制時可能遇到的捨入誤差）為 050。 引數和引數 術語引數和引數在不同的程式語言中可能會具有不同的含義。有時它們可以互換使用，並且以上下文區分含義。術語引數（也稱為形式引數（形參，））通常用來指該變數作為在函式定義中變數的內容。而引數（也稱為實際引數（實參，））是指在函式呼叫中提供的實際輸入。例如，如果將一個函式定義為 def f x ，x 則為引數。若定義有 a f a 來呼叫函式，那麼這裡的 a 就是引數。 引數是一個（未繫結實際值的）變數，而引數可以是一個值或變數，或者是涉及值和變數的更複雜的表示式。在由值呼叫的情況下，所傳遞給函式是自變數的值。例如 f 2 和 a 2 f a 對函式的呼叫是相同的，在以變數作為引數透過引用呼叫時，若函式呼叫的語法可以保持不變，則傳遞的是對該變數的引用。具體傳值呼叫或者是傳引用呼叫的細節規範則由函式的宣告以及定義中進行。 一般而言，引數出現在過程定義中，引數則出現在過程呼叫中。在函式 f x xx 的定義中，變數 x 是引數。在函式 f 2 呼叫中，值 2 是該函式的引數。簡單而不太準確的概擴來說引數是型別，而引數是實作。 引數是過程的固有屬性，包含在其定義中。例如，在許多語言中，將兩個提供的整數加在一起併計算總和的過程將需要兩個引數，每個整數一個。通常，可以使用任意數量的引數或完全不使用引數來定義過程。如果過程具有引數，則其定義中指定引數的部分稱為其引數列表（parameter list）。 相反，引數是呼叫過程時提供給過程的表示式，其通常是一個與引數之一匹配的表示式。與引數（它們構成過程定義的不變部分）不同，自變數在呼叫之間可能有所不同。每次呼叫過程時，過程呼叫中指定引數的部分稱為引數列表（argument list）。 儘管引數通常也被混稱為引數，但是在執行時呼叫子例程時，有時會將引數視為分配給引數變數的實際值或引用。在討論正在呼叫子例程的程式碼時，傳遞給子例程的任何值或引用都是引數。 在討論子例程定義中的程式碼時，子例程的引數列表中的變數是引數，而執行時引數的值則會是引數。例如，在 C 語言中，處理執行緒時通常會傳入 void 型別的引數並將其強制轉換為預期的型別： void ThreadFunction void pThreadArgument 將第一個引數命名為 pThreadArgument 而不是 pThreadParameter 是正確的。 在執行時，我們使用的值是一個引數。 如上所述，在討論子例程定義時保留術語引數。 為了更好地理解它們之間的區別，請考慮以下用 C 語言編寫的函式： int Sum int addend1 int addend2 return addend1 addend2 函式 Sum 具有兩個引數，分別名為 addend1 和 addend2，這個函式將傳遞給引數的值相加，然後將結果返回給子例程的呼叫方（使用 C 語言編譯器自動提供的技術）。 呼叫 Sum 函式的程式碼如下所示： int value1 40 int value2 2 int sum_value Sum value1 value2 變數 value1 和 value2 用值初始化。在這種情況下，value1 和 value2 都是 sum 函式的引數。 在執行時，分配給這些變數的值作為引數傳遞給函式 Sum。在 Sum 函式中，將會對引數 addend1 和 addend2 進行求值，分別得出引數 40 和 2。將新增引數的值，並將結果返回給呼叫方，在此將其分配給變數 sum_value。 由於引數和引數之間的差異，有可能向過程提供不合適的引數，也可能提供過多或過少的引數，要麼一個或多個引數可能是錯誤的型別，或者是以錯誤的順序提供了引數。這些情況中的任何一種都會導致引數列表和引數列表之間不匹配，並且該過程通常會返回意外的答案或生成執行期錯誤。 資料型別 在強型別程式語言中，必須在過程宣告中指定每個引數的型別。使用型別推斷的語言會嘗試從函式的主體和用法中自動推斷型別。動態型別的程式語言則會將型別解析推遲到執行時。弱型別語言幾乎沒有型別解析，甚至依靠程式設計師來確保正確性。 一些語言使用特殊的關鍵字（例如 void）來指示該子例程沒有引數。在形式型別理論中，此類函式採用空引數列表（其型別不是 void，而是）。 引數傳遞 將引數分配給引數的確切機制稱為引數傳遞（argument passing），該機製取決於可以使用關鍵字來指定的引數求值策略（通常為按值傳遞）。 預設引數 某些程式語言（例如 Ada，C，Clojure，Common Lisp，Fortran 90，Python，Ruby，Tcl 和 Windows PowerShell）允許在子例程的宣告中顯式或隱式給出缺省引數。這允許呼叫者在呼叫子例程時忽略該引數。如果顯式給出了預設引數，則如果呼叫者未提供該值，則使用該值。如果預設引數是隱式的（有時透過使用諸如 Optional 之類的關鍵字），則該語言將提供一個通常值（例如 null、Empty、0、空字串等）。 PowerShell 示例： function doc g 121 g gigawatts g gigawatts Great Scott PS doc 121 gigawatts 121 gigawatts Great Scott PS doc 88 88 gigawatts 88 gigawatts Great Scott 預設引數可以看作是可變長度引數列表的一種特殊情況。 可變長度引數列表 某些語言允許將子例程定義為接受可變數量的引數。對於此類語言，子例程必須遍歷引數列表。 PowerShell 示例： function marty args foreach back to the year _ PS marty 1985 back to the year 1985 PS marty 2015 1985 1955 back to the year 2015 back to the year 1985 back to the year 1955 命名引數 某些程式語言（例如 Ada 和 Windows PowerShell）許子例程具有命名引數。這使呼叫程式碼更具。它還為呼叫者提供了更大的靈活性，通常允許更改引數的順序，或者根據需要省略引數。 PowerShell 示例： function jennifer adjectiveYoung adjectiveOld Young Jennifer Im adjectiveYoung Old Jennifer Im adjectiveOld PS jennifer fresh experienced Young Jennifer Im fresh Old Jennifer Im experienced PS jennifer adjectiveOld experienced adjectiveYoung fresh Young Jennifer Im fresh Old Jennifer Im experienced 函式語言中的多個引數 在 lambda 演算中，每個函式只有一個引數。通常認為具有多個引數的函式在 lambda 演算中表示為具有第一個引數的函式，並返回具有其餘引數的函式。這種轉換也被稱為柯里化（Currying）。一些程式語言（例如 ML 和 Haskell）遵循此方案。在這些語言中，每個函式都只有一個引數，看起來像多個引數的函式的定義，實際上是返回一個函式的函式的定義的語法糖等。在這些語言以及 lambda 演算中的函式應用是的，因此，這種操作看起來會像是將函式應用於多個引數的函式先將函式應用於第一個引數，然後將結果函式應用於第二個自變數，並依此類推。 輸出引數 輸出引數，也稱為出參或返回引數，是一種用於輸出而不是更通常的使用用於輸入的引數。在某些語言中，尤其是 C 和 C ，輸出引數是一種習慣用法，而其他語言則內建了對輸出引數的支援。內建支援輸出引數的語言包括 Ada、Fortran、SQL 的各種拓展程式（例如：PLSQL 和 TransactSQL）、Ｃ 和Net Framework、Swift 以及手稿語言 TScript。 更準確地說，引數模式或引數共有三種型別：輸入引數（入參）、輸出引數（出參）、輸入輸出引數（出入參），這些引數往往使用 in、out、inout 來進行表示。輸入引數輸入引數（針對輸入引數的引數）必須是一個值，例如已經被初始化了的變數或常值，而且不能重新定義獲分配它。輸出引數必須是可分配變數，但不必初始化而且任何現有值均不可存取輸入值，執行函式後必須分配一個值。輸入輸出引數必須是已初始化了的可分配變數，並且可以選擇給其分配一個值。確切的要求和執行情況因語言而異，例如在 Ada 83 中，即使分配後也只能分配輸出引數（在 Ada 95 中刪除了該引數，以消除對輔助累加器變數的需要）。這有些類似於值的概念，也就是左值（，具有值）、右值（，可分配）以及左右值（，具有值且可分配），不過這些術語在 C 語言中有特殊含意。 在某些情況下，只有輸入和輸入輸出是有區別的，而輸出則被視為輸入 輸出的特定用途，而在其他情況下，僅支援輸入和輸出（但不支援輸入輸出）。預設模式因語言而異：在 Fortran 90 中，預設輸入 輸出，在 C＃和 SQL 擴充套件中，預設輸入 輸出，在 TScript 中，每個引數都明確指定為輸入或輸出。 從語法上講，引數模式通常在函式宣告（例如在 C＃中：void f out int x）中用關鍵字表示。通常，輸出引數通常放在引數列表的末尾以清楚地區分它們。TScript 使用另一種方法，其中在函式宣告中列出了輸入引數，然後列出了輸出引數，並用冒號分隔，並且函式本身沒有返回型別，如在此函式中一樣，該函式用於計算文字的大小分段： TextExtent WString text Font font Integer width Integer height 引數模式是指稱語義的一種形式，其表明了程式設計師的意圖並允許編譯器捕獲錯誤來應用最佳化，它們不一定暗示操作語義（引數傳遞的實際發生方式）。值得注意的是，雖然輸入引數可以透過值呼叫實現，而輸出和輸入輸出引數可以透過引用呼叫實現，這是在沒有內建支援的情況下以語言實現這些模式的直接方法，但也並非總是如此實施。《Ada 83 基本原理》中詳細討論了這種區別，其中強調了引數模式是從中實際實現的引數傳遞機制（透過引用或透過複製）抽像出來的。例如，在 C＃中，按值傳遞輸入引數（預設，無關鍵字），而按引用傳遞輸出和輸入 輸出引數（out 和 ref），而在 PL SQL 中傳遞輸入引數（IN）透過引用，預設情況下透過值傳遞輸出和輸入 輸出引數（OUT 和 IN OUT），並將結果復制回去，但是可以使用 NOCOPY 編譯器提示透過引用傳遞。 與輸出引數在語法上相似的構造是將返回值分配給與函式名稱相同的變數。 可以在 Pascal 和 Fortran 66 和 Fortran 77 中發現，此處使用 Pascal 示例： function f x y integer integer begin f x y end 這在語義上是不同的，因為在呼叫時僅對函式進行求值不會從呼叫範圍傳遞變數來儲存輸出。 使用 輸出引數的主要用途是從一個函式返回多個值，而輸入 輸出引數的用途是使用引數傳遞（而不是像全域性變數那樣在共享環境中）來修改狀態。 返回多個值的一個重要用途是解決返回值和錯誤狀態的。 例如，要從 C 函式中返回兩個變數，可以寫： int width int height F x width height 其中 x 是輸入引數， width 和 height 是輸出引數。 C 和相關語言的一個常見用例是異常處理 ，其中函式將返回值放在輸出變數中，並返回一個布林值，該布林值對應於函式是否成功。 一個典型的例子是NET 中的 TryParse 方法，尤其是 C＃，它將字串解析為整數，成功則返回 true ，失敗則返回 false 。 其具有以下形式： public static bool TryParse string s out int result 可以這樣使用： int result if Int32TryParse s result exception handling 類似的考慮適用於返回幾種可能型別之一的值，其中返回值可以指定型別，然後將值儲存在幾種輸出變數之一中。 缺點 在現代程式設計中，通常不鼓勵使用輸出引數，因為它們笨拙、令人困惑且級別太低，普通的返回值相當容易理解和使用。值得注意的是，輸出引數涉及具有副作用（修改輸出引數）的函式，並且在語義上與引用相似，比純函式和值更容易混淆，並且輸出引數與輸入 輸出引數之間的區別可能微妙。 此外，由於在通常的程式設計樣式中，大多數引數只是輸入引數，因此輸出引數和輸入輸出引數是異常的，從而容易引起誤解。 輸出和輸入輸出引數會阻止函式組合，因為輸出儲存在變數中，而不是表示式的值中。 因此，必須首先宣告一個變數，然後函式鏈的每一步都必須是一個單獨的語句。 例如，在 C 中，以下函式組成： Object obj G y F x 當寫有輸出和輸入輸出引數時，可以寫為（對於 F 是輸出引數，對於 G 是輸入 輸出引數）： Object obj F x obj G y obj 在具有單個輸出或輸入 輸出引數且沒有返回值的函式的特殊情況下，如果該函式還返回輸出或輸入輸出引數（或在 C C 中是其地址），則可以構成函式，在這種情況下，以上內容將變為： Object obj G y F x obj 替代方式 輸出引數的用例有多種選擇。 為了從一個函式返回多個值，一種替代方法是返回一個元組 。 從語法上講，如果可以使用自動序列拆包和並行賦值 （例如在 Go 或 Python 中），這會更清楚： def f return 1 2 a b f 為了返回幾種型別之一的值，可以使用標籤聯合 。最常見的情況是 （ 可選型別 ），其中返回值可以為 null 以指示失敗。對於異常處理，可以返回可為 null 的型別，也可以引發異常。 例如，在 Python 中，可能有以下兩種情況之一： result Parse s if result is None exception handling 或者，更慣用的方法： try result Parse s except ParseError exception handling 不需要區域性變數並在使用輸出變數時復制返回值的微最佳化也可以透過足夠複雜的編譯器應用於常規函式和返回值。 使用 C 和相關語言輸出引數的通常替代方法是返回包含所有返回值的單個資料結構。 例如，給定一個封裝寬度和高度的結構，可以這樣寫： WidthHeight width_and_height F x 在面向物件的語言中，通常不使用輸入輸出引數，而是透過傳共享物件呼叫，將引用傳遞給物件然後對物件進行突變來使用呼叫 ，而不更改變數所引用的物件。 相關條目 求值策略 運算子過載 自由變數和約束變數 參考資料 Category 程式設計小作品 Category 變數 Category 子程式