Chapter2_C與C++——2.2 函數

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;  

求韓信有多少兵?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章