在使用函數之前應該先宣告,事先通知編譯器該函數的型別:換句話說,
一個宣告即是描述一個函數的介面。宣告至少應指明函數返回值的型別,如下例所示:
int rename();
這一行程式碼宣告 rename()是一個函數,其返回值的型別是 int 型別。因為在預設情況下,函數名是外部可見的識別符號,所以上述宣告等同於:
extern int rename();
該宣告沒有包含關於函數引數的數量和型別等相關資訊。因此,編譯器無法檢查呼叫該函數時所傳入的引數是否正確。如果呼叫該函數時傳入的引數有別於該函數的定義,那麼會導致嚴重的執行錯誤。
為了避免這樣的錯誤,應該在宣告函數時,同時宣告函數的引數。換句話說,所宣告的應該是一個函數原型(function prototype)。例如,標準庫函數 rename()(它用於修改檔名)的原型如下:
int rename( const char *oldname, const char *newname );
該函數需要兩個引數,型別都是指向 const char 的指標。換句話說,此函數使用這兩個指標的目的是為了讀取 char 物件,所以引數可以是字串字面量。
在原型宣告中,引數的識別符號是可選的,可以不寫。如果將引數名包含進去,這些名稱的作用域也僅限於該原型中。對於編譯器來說引數名是沒有意義的,它們最多和註釋一樣告訴程式設計師該引數的目的。
例如,在函數 rename()的原型中,引數名稱 oldname 和 newname 用來告訴程式設計師,在呼叫函數時,舊的檔名寫在前而,新的檔名寫在後面。對於編譯器來說,上述原型宣告等同於沒有給出引數名的宣告:
int rename( const char *, const char * );
標準標頭檔案中包含了標準庫函數的原型。如果想在程式中呼叫函數 rename(),可以通過在程式碼中包含標頭檔案 stdio.h 的方式來達到宣告的效果。
通常,可以將自己所定義的函數原型放在一個標頭檔案中,這樣在其他任何原始碼檔案中,通過 include 命令來包含該標頭檔案,則可以使用這些函數。
宣告可選引數
C 語言允許定義引數數量可變(variable number of argument)的函數。關於此類函數,最常見的例子是 printf(),它具有下面的原型:
int printf( const char *format, ... );
如同該例所展示的,這個引數型別列表的最後一個逗號後,跟著的是省略號(…)。省略號代表了可選引數。函數 printf()呼叫的第一個引數必須是 char 指標。這個引數後面可能會跟著其他引數。原型並沒有包含可選引數的數量或型別等相關資訊。
宣告長度可變的陣列引數
當宣告某個函數,其引數是長度可變陣列(variable-length array),除了在函數定義的頭部,其他地方都可以使用星號(*)來表示陣列長度。如果使用非常數的整數表示式來定義陣列長度,編譯器會將它視為星號。例如,下面所有的宣告都可當作函數 maximum()的原型:
double maximum( int nrows, int ncols, double matrix[nrows][ncols] );
double maximum( int nrows, int ncols, double matrix[ ][ncols] );
double maximum( int nrows, int ncols, double matrix[*][*] );
double maximum( int nrows, int ncols, double matrix[ ][*] );