2.2 函數
2.2.1 函數基礎
所謂函數,是指按照某種規律,將輸入轉變成輸出的系統。
我們可以用c語言描述這樣的系統。
int fun0(int a, int b)
{
return (a+b)*(a-b);
}
以上是一個函數的定義,可以看出,定義函數需採用以下語法結構:
返回值類型 函數名(參數類型 參數1, ... ,參數類型 參數n)
{
函數體
}
函數的命名規則與變量的命名規則一致,只能包括下劃線,英文字符和0~9數字,並且數字不能作爲首字母出現。
函數的參數是一組僅在函數內部可見的變量,這些變量的值,由調用者傳入:
int a = 5;
fun0(a, 3); // 計算(5+3)*(5-3).
在定義函數的時候寫的參數名稱稱作形式參數,簡稱形參。而這裏在調用時傳入的a和3稱作實際參數,簡稱實參。
函數的返回值通過 return 語句返回給調用者:
int c = fun0(5, 3); // c=16.
函數可以沒有輸入,此時函數的參數列表應該爲 void,或者不寫。
int fun1(void)
{
return 9; // fun1不依賴任何參數,固定返回整數9.
}
函數也可能沒有返回值,此時返回類型爲 void:
void fun2(int a)
{
printf("A = %d.\n", a); // 函數不返回任何內容,僅打印參數a的值.
}
int b;
b = fun2(0x10); // 這種寫法是錯的,因爲fun2沒有返回值,所以無法爲變量b賦值.
對於大部分 c/c++ 程序而言,有一個特殊的函數,它是整個程序的總入口——main函數。main函數的第一條語句便是整個程序的第一條指令。
#include <stdio.h> // 包含printf等標準輸入輸出函數
int fun0(int a, int b)
{
return (a+b)*(a-b);
}
int main(void)
{
int a=5, b=3;
printf("我是第一條被執行的語句!\n");
printf("a^2-b^2=%d", fun0(a, b));
printf("我是第三條被執行的語句!\n");
return 0;
}
以上,是我們迄今爲止編寫的最完整的 c 語言程序。它包含了該程序的總入口函數 mian,定義並初始化了兩個局部變量 a 和 b,通過 printf 語句進行了一些輸出,return 0 代表程序正確執行。另外,我們定義了了一個函數 fun0,並且爲了讓程序能被編譯通過,我們通過 include 包含了一些c標準庫對外聲明的函數等,用於聲明 printf 函數。
以上你所見的,是所有 main 函數形式中的一種。main 函數不但可以返回零,還可以返回其他值給調用者。也可以接收來自調用者傳入的一些參數,這時候 main 函數的形式如下:
int main(int argc, char* argv[])
{
...
}
2.2.2 函數調用
函數之間可以相互調用,例如在 fun3 中調用 fun4 的代碼如下:
/**
* @file example0.c
*/
#include <stdio.h>
static void fun4(void); // 由於 fun4 是在被使用後定義的,因此需要在使用前聲明.
void fun3(void)
{
printf("This fun3.\n");
fun4(); // 調用 fun4.
}
/**
* @brief static 關鍵字限定了 fun4 只能在本文件中使用,不能在其他文件中使用.
*/
static void fun4(void)
{
printf("This fun4.\n");
}
int main(void)
{
fun3(); // fun3 是在 main 函數前定義的,因此不需要再次聲明.
return 0;
}
有一種非常獨特的函數調用方法,被稱作第歸調用:
/**
* @file example1.c
*/
void fun5(void)
{
fun5();
}
int main(void)
{
fun5();
return 0;
}
在上面程序中,main 函數中的 return 語句永遠不會被執行。因爲 fun5 這個函數不斷的調用自己,致使程序一直被執行下去。
實際上,每次調用函數都會壓棧,fun5 無窮無窮盡的調用自己,只會導致堆棧溢出,或者被看門狗檢測到死循環。通常,我們不會這樣編寫程序,而是在 fun5 中增加條件判斷,在某些情況下不再調用自己,從而使程序可以返回。第歸調用在某些情況下是非常有用的。
練習
1、編寫第歸調用程序解決下列問題:
一般而言,兔子在出生兩個月後,就有繁殖能力,一對兔子每個月能生出一對小兔子來。如果所有兔子都不死,那麼一年以後可以繁殖多少對兔子?
2、韓信爲了知道多少兵,同時又不讓敵人知道士兵數目,便讓士兵排隊報數:
按1~5報數,最後一個士兵報數爲1;
按1~6報數,最後一個士兵報數爲5;
按1~7報數,最後一個士兵報數爲4;
按1~11報數,最後一個士兵報數爲10;
求韓信有多少兵?