函數原型
此條目需要補充更多來源。 (2018年12月17日) |
在電腦程式設計中,函數原型(英語:Function prototype)或函數介面(英語:Function interface)是用於指定函數的名稱和型別簽章(元數,參數的資料型別和回傳值型別)的一種省略了函數體的函數宣告。雖然函數宣告規定了函數是如何被實作的,但僅包括對介面的定義(即接受的資料型別和回傳的資料型別),並不包括對函數體的定義。
函數原型被廣泛應用於C、C++ 語言程式碼的上下文中,透過在標頭檔中放置函數的前向宣告來允許將程式碼拆分為多個翻譯單元。即編譯器可以單獨編譯目標文件的這部分內容,然後由連結器組合成可執行檔案或函式庫。現代編譯器(如Arduino IDE)不再需要函數原型,因為這些是在編譯時被確定和宣告的。
在原型中,參數名是非必需的(C/C++中存在函數原型作用域,這使參數名的作用域被限制在函數定義內),但是,型別和修飾詞都是必需的(如指標或常數參數)。
舉例
有函數原型如下:
void Sum(int a,int b);
或
void Sum(int, int);
首先,函數原型包括函數簽章(英語:function signature),函數名,回傳型別和訪問修飾詞。在該例中,函數的名稱是「Sum」。函數簽章確定參數的數量及其型別。在上面的範例中,回傳型別為「void」,這意味着該函數不會回傳任何值。要注意的是第一個範例中的參數名稱是非必需的,甚至實際定義時與函數原型中宣告的不同也沒關係。
應用
在早期的C語言中,如果一個函數之前沒有宣告,並且函數名出現在表達式中,後面跟着左括號,那麼它會被隱式宣告為回傳int
型別的函數,並且對它的參數沒有任何假設。在這種情況下,當函數應用於某些參數時,編譯器將無法執行參數型別和語法元數的編譯時檢查。這可能會導致問題。以下程式碼說明了隱式宣告的函數的行為未定義的情況。
#include <stdio.h>
/* 简体中文:
* 如果提供此函数原型,编译器将在main函数中捕获错误。
* 如果省略,则错误可能会被忽略。
*/
/* 正體中文:
* 若提供此函式原型,編譯器將在main函式中發現錯誤。
* 若省略,則錯誤可能會被忽略。
*/
int MyFunction(int n); /* 简:函数原型 正:函式原型 */
int main( void ) /* 简:调用函数 正:呼叫函式 */
{
printf("%d\n", MyFunction()); /* Error: forgot argument to MyFunction */
return 0;
}
int MyFunction( int n ) /* 简:被调用的函数声明 正:被呼叫的函式宣告 */
{
if (n == 0)
{
return 1;
}
else
{
return n * MyFunction(n - 1);
}
}
函數MyFunction被呼叫時會請求一個位於堆疊或暫存器中的整數型別參數。如果省略函數原型,編譯器將無法執行此操作,函數MyFunction將在堆疊上的其他一些數據上執行(可能是回傳地址或當前不在作用域中的變數的值)。透過包含函數原型,您將通知編譯器函數myFunction接受一個整型參數,並使編譯器能夠擷取這些型別的錯誤,並使編譯過程順利執行。
透過包含函數原型,你可以告知編譯器函數MyFunction接受一個整數參數,並使編譯器能夠擷取這些型別的錯誤,使編譯過程順利執行。該特性已從C99標準中刪除,因此省略函數原型將導致編譯錯誤。[來源請求]
建立函式庫介面
透過在標頭檔中放置函數原型,可以為函式庫指定介面。
宣告類別
在C++中,函數原型也在類別定義中使用。
參見
參考文獻
- Kernighan, Brian W.; Ritchie Afree, Dennis M. The C Programming Language 2nd. Upper Saddle River, NJ: Prentice Hall PTR. 1988. ISBN 0-13-110362-8.