一、遞歸函數
- 遞歸概念:如果一個函數內部,包含了對自身的調用,則該函數稱為遞歸函數。
- 要點:
-
- 只有能被表達為遞歸的問題,才能用遞歸函數解決。
- 遞歸函數必須有一個可直接退出的條件,否則會進入無限遞歸。
- 遞歸函數包含兩個過程,一個逐漸遞進(答案越來越接近)的過程,和一個逐漸回歸(條件越來越接近)的過程。
- 遞歸問題:
- 依次輸出 n 個自然數:
- 階乘。 寫一個函數,輸入參數數據(階乘數),比如5,返回1*2*3*4*5
- 示例代碼:
#include <stdio.h>// 例子1:輸出自然數
void func1(int num)
{if (num < 0) // 1、可退出條件(自然數:非負整數){return;}func1(num-1); // 2、逐漸回歸(條件越來越接近)的過程printf("%d ", num); // 3、逐漸遞進(答案越來越接近)的過程
}// 例子2:階乘
int func2(int num)
{if (num > 1) // 1、可退出條件(自然數:非負整數){num = num*func2(num-1); // 2、逐漸回歸(條件越來越接近)的過程}return num; // 3、逐漸遞進(答案越來越接近)的過程
}// 主函數
int main(void)
{// 例子1:func1(10);// 例子2:int ret = func2(5);printf("ret == %d\n", ret);return 0;
}
可以理解為,如果條件成立,就可以一直調用自己,然后就是每次調用都有打印,但不是立即輸出出來,而是當退出條件滿足時它才把所有之前打印的按倒序打印出來。例如下圖可以幫助理解。
?
二、靜態函數
- 背景知識:普通函數都是跨文件可見的,即在文件 a.c 中定義的函數可以在 b.c 中使用。
- 靜態函數:只能在定義的文件內可見的函數,稱為靜態函數。
- 語法:
staitc void f(void) // 在函數頭前面增加關鍵字 static ,使之成為靜態函數
{// 函數體
}
- 要點:
- 靜態函數主要是為了縮小函數的可見范圍,減少與其他文件中重名函數沖突的概率。
- 靜態函數一般被定義在頭文件中,然后被各個源文件包含。
- 圖解:
?
- 示例代碼:
main.c文件
#include <stdio.h>extern int num;
extern void A_func1(void);
extern void B_func1(void);// 主函數
int main(int argc, char const *argv[])
{num = 200;printf("num == %d\n", num);A_func1();// B_func1(); // 此函數在b.c中,但是被static關鍵字屏蔽了,無法在此處使用return 0;
}
a.c文件:
#include <stdio.h>// 一、全局變量和函數
// 全局變量
int num = 100;// 全局函數
void A_func1(void)
{printf("A_func1........\n");
}// 二、本文件的變量和函數
// 全局變量// 全局函數
b.c文件
#include <stdio.h>// 一、全局變量和函數
// 全局變量// 全局函數// 二、本文件的變量和函數
// 全局變量
static int num = 100;// 全局函數
static void B_func1(void)
{printf("B_func1........\n");
}
三、回調函數(一般不用)
- 概念:函數實現方不調用該函數,而由函數接口提供方間接調用的函數,稱為回調函數。
- 要點:
- 示例中函數 sighandler 是回調函數。
- signal() 將函數回調函數傳遞給內核,使得內核可以在恰當的時機回調 sighandler。
- 應用開發者和內核開發者只要約定好回調函數的接口,即可各自開發,進度互不影響。
- 示例1:系統中的信號處理,是一個典型的利用回調函數的情形。
- 示例2:間接調用
#include <stdio.h>
void func1(void)
{printf("1111111111\n");
}void func2(void)
{func1();
}int main(int argc, char const *argv[])
{// 1、直接調用func1();// 2、間接調用func2();// 為什么我們要間接調用???// 普通函數的寫法void func(void){} // 線程函數的寫法:void* PT_func(void){func();}return 0;
}
- 示例3:涉及函數指針的回調函數
#include <stdio.h>
// 普通函數
// 加法
int add(int a, int b)
{return a+b;
}// 減法
int substration(int a, int b) // 該函數的類型:int (int, int);
{return a-b;
}// 回調函數(間接調用)
int callback(int a, int (*p)(int, int), int b)
{printf("%d\n", p(a, b));
}// 主函數
int main(int argc, char const *argv[])
{// 1、直接使用回調函數callback(100, add, 200);callback(100, substration, 200);// 2、間接使用回調函數(覺得這個名字不夠準確表達,可以利用這個方式進行重新命名)int (*count)(int, int (*)(int, int), int) = callback;count(100, add, 200);count(100, substration, 200);return 0;
}
至此,希望看完這篇文章的你有所收獲,我是Bardb,譯音八分貝,道友,下期見!