當一個的主函數太過龐大時,會將主函數按功能進行拆分,根據是否須要向外部提供接口,分爲靜態函數和普通函數,
普通的函數是跨文件可見的, 可是若是是靜態函數的話他的可見範圍會被縮小到本文件可見,外部文件是沒法進行調用的。函數
static int max (int x, int y) { //函數體 } //靜態函數主要功能是能夠縮小該函數的可見範圍,減小函數重名的機率; // 通常靜態函數會被定義在頭文件中,在須要使用的文件中能夠包含該文件便可使用。
若是一個函數內部有本身調用本身的語句,則它是遞歸函數。
注意:
emsp;1.遞歸函數必須有結束條件,否則會一直調用下去,將棧溢出,棧崩潰,最後致使程序異常退出;
emsp;2.遞歸函數包含兩個過程,一個是逐層遞進,和逐步遞歸。指針
/*倒序打印 */ void func( int num ){ if (num > 1){ func(num-1); } printf("%d\n" , num ); }
注意:
1.在遞歸函數使用的過程當中,棧空間消耗很是大,遞歸的層次越多棧空間剩餘空間間越少,很容易會把棧空間耗盡 。
2.在層層遞進的過程當中問題的規模,應該逐步減少,也就是某個形式參數應該逐步減少,每次遞歸判斷該形式參數是否知足返回條件。code
 每一個函數都有一個入口地址,但調用此地址時就會調用此函數。函數指針就是用來保存函數的入口地址的,當函數的實現方不方便直接調用某個功能,可將函數的入口地址傳遞給函數指針,調用此函數指針即可以間接調用原來的函數,這種調用方式稱爲回調函數。遞歸
bool func_1( int (*p) (int ,int )); int func_2(int a , int b); int main(int argc, char const *argv[]) { bool a = func_1(func_2);//func_2是一個函數的地址 if (a) { printf("函數調用成功 !! \n"); } else{ printf("函數調用失敗 !! \n"); } return 0; } bool func_1( int (*p) (int ,int ) ){ if ( NULL == p ){// 先判斷p是否指向一個NULL return false ; } printf("我在函數1 !!\n"); int num = p(103 , 229);//經過函數指針P來調用函數func_2 printf("num:%d\n" , num); return true ; } int func_2(int a , int b){ return a<b ? a:b ; }
注意:
1.傳遞和接收函數地址時&,*可省略。接口
//冪運算 int exponentiation(int n, int i){ if(i == 0){ return 1; } else{ return exponentiation(n, i-1)*n; } }
//階乘 int Factorial(int n) { if(n == 1) {//使遞歸結束的條件 return 1;//1! 等於1 } else{//使遞歸進行的條件 return(Factorial(n-1) * n);//n! = (n-1)! * n; } }