C 語言初學教材 - 第一章 函數

簡單的例子的程式碼如下

#include <stdio.h>

int main(void)
{
    int month, day, hour, min;
    char *name;
    
    month = 7;
    day = 27;
    hour = 9;
    min = 45;
    name = "kaiching";
    
    printf("\n\n今天是 %d 月 %d 日\n", month, day);
    printf("現在是上午 %d:%d\n", hour, min);
    printf("哈囉, %s!\n\n", name);
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:csimple.c
    功能:簡單顯示訊息的例子
    作者:張凱慶
    時間:西元2010年7月 */


我們把注意力放到第 3 到 19 行,也就是下圖中的函數 (function) 定義區



C 程式是以函數為執行單位,每個可執行的 C 程式都要有個函數 main() ,因為 main 為 C 語言函數的保留字,編譯 C 程式時,編譯器 (compiler) 都會先尋找名為 main 的函數作為程式執行的起點。


若將簡單例子中的函數 main() 更名為 my_function() ,重新編譯會得到如下的錯誤



意思大體是說 my_function 的名稱是沒有定義的,編譯器沒找到 main 的名稱。


函數的定義格式如下
回傳值型態 函數名稱(參數列)
{
    ....
    
    return 回傳值;
}


上面第一列為函數的標頭,然後左大括弧 { 一直到右大括弧 } 便是函數定義的區域,右大括弧的上方有一行 return 陳述,這便是函數回傳數值的地方。若以簡單例子的函數 main() 來看,函數標頭與回傳的 return 陳述標示如下



通常自行定義的函數可以先做函數原型 (prototype) 的宣告,如
回傳值型態 函數名稱(參數列);


函數原型的宣告會放在 main() 之前,而通常不會對 main() 宣告函數原型。先行宣告函數原型,編譯器會檢查函數原型的回傳值型態及參數列中各參數的型態是否與定義相同。


C 語言的函數可以有回傳值 (return value) ,也可以沒有回傳值。回傳值的意思可以想成函數的計算結果,這跟數學中函數的觀念是一樣的,每個輸入值只會對應到唯一的輸出值,因此 C 語言的函數只能有一個回傳值。另外, C 語言中凡是值都有型態,因此回傳值也有所屬的資料型態,這在定義或宣告時都需要標明。


函數也可以沒有回傳值,沒有回傳值就像只是做一些工作,這些工作並不需要計算結果。 C 語言中沒有回傳值的函數須宣告為 void , void 也為 C 語言的關鍵字 (keyword) 之一
void 函數名稱(參數列);


C 語言的函數可以有參數 (parameter) ,也可以沒有參數。所謂的參數就像數學中函數的輸入值, C 語言的函數可以有多個參數,就像多元方程式一樣。函數名稱後的小括弧為宣告參數的地方,可有多個,所以稱之為參數列。因為 C 語言中凡是值都有型態,所以參數也須宣告所屬的資料型態。


同樣的,函數也可以沒有參數,這時候參數列就須宣告為 void
回傳值型態 函數名稱(void);


簡單例子中的函數 main() 不接受參數,所以函數定義的標頭為
int main(void)


int 為整數資料型態,同時 int 也為關鍵字之一,函數 main() 的回傳值定義為回傳一個 int 型態的數值。


注意,函數名稱為識別字之一,以上舉例的「函數名稱」僅作為位置標示,通常編譯器只接受英文、數字及底線符號作為識別字,使用中文作識別字名稱會發生編譯錯誤。


問題與討論
  1. 為什麼要作函數原型的宣告?有什麼好處?
  2. 定義函數時可不可以不寫回傳值的型態?編譯器會預設某種型態給回傳值嗎?
  3. 如果一個需要回傳整數值的函數沒有寫 return 陳述,編譯時會發生問題嗎?
  4. 試舉出數個合法的識別字名稱。




沒有留言: