接續上篇[C語言基礎及指針③函數與二級指針](http://www.jianshu.com/p/184df8a1f195)
在上一篇中 , 我們學習了函數與二級指針 , 函數和java中的方法類似 , 只是缺少了訪問控制符 , 二級指針也就是指針的指針 , 指針里面存儲的是指針的地址 , 可以通過`*`操作符不斷往上追溯 , 然后通過內存地址操作內存空間 。
### 函數指針
當我們定義一個函數的時候 , 這個函數也會像變量一樣 , 會有一個內存地址 , 我們也可以將函數定義成為一個函數指針 , 但函數不同于變量 , 變量存儲的是固定的值 , 而函數指針存儲的是函數的內存地址 。下面我就用一個示例來說明:
```c
// windows 彈出框頭文件
#include <Windows.h>
/*函數*/
void message() {
MessageBox(NULL, "我是彈出框", "消息", NULL);
}
void main() {
// 函數指針定義 , 返回值(函數指針名稱)(函數參數) = 函數名稱
void(*func_p)() = &message;
// 調用函數指針
func_p();
printf("函數指針地址:%#x\n", func_p);
getchar();
}
```
輸出:
```c
函數指針地址:0xe6d31073
```
我們可以通過函數指針地址 , 反匯編我們的程序員 , 查看他的跳轉

由上圖我們可以看出 , 我們的函數指針 , 通過jmp指令跳轉到另一個地址上 , 下面我來看看message的地址里面是什么:

我們看到通過函數指針里面存儲的是一個函數的地址 ,然后通過一個jmp指令調到我們的函數定義執行 。
有了我們的函數指針 , 我們可以做很多事情 , 下面我們來看一個簡單的示例:
```c
int add(int num1, int num2) {
return num1 + num2;
}
int minus(int num1, int num2) {
return num1 - num2;
}
// 將函數指針直接定義到函數形參中 , 類似java中的多態
// 我們可以函數指針作為函數參數傳入
void showMsg(int(*c)(int num1, int num2), int a, int b) {
int r = c(a, b);
printf("計算完成=%d\n", r);
}
void main() {
showMsg(add, 10, 10);
showMsg(minus, 30, 2);
}
getchar();
```
輸出:
```c
計算完成=20
計算完成=28
```
通過傳入函數地址 , 就可以調用函數進行運算 , 我們只要按照傳入的參數和返回值 , 寫我們自己的函數 , 通過這個方法 , 我們就可以統一的實現我們函數的功能 。下面我們來寫一個回調函數:
```c
/*模擬網絡請求回調*/
void requestNet(char* url , void(*callBack)(char *)) {
printf("請求地址:%s , 正在請求網絡....\n",url);
// 模擬網絡請求耗時
Sleep(2000);
char* str = "我是請求的網絡數據 , 落花有意隨流水 , 流水無情戀落花\n";
callBack(str);
}
/*回調函數*/
void netCallBack(char *str) {
printf("網絡請求回調\n");
printf("請求到的數據:%s" ,str);
}
void main() {
char* url = "www.zhuyongit.com";
requestNet(url, netCallBack);
}
```
輸出:
```c
請求地址:www.zhuyongit.com , 正在請求網絡....
網絡請求回調
請求到的數據:我是請求的網絡數據 , 落花有意隨流水 , 流水無情戀落花
```
我們模擬了網絡請求的常見封裝 , 使用一個回調函數來接收我們請求回來的數據 。函數指針很強大 , 我們可以直接傳入函數名稱 , 再另一個函數里面執行我們傳入的函數 , 如果是在java里面 ,我還需要傳入一個對象 , 再通過對象來調用方法 , 在C語言里面 , 直接通過函數指針就可以搞定 。
Android程序員學C系列:
[C語言基礎及指針①](http://www.jianshu.com/p/4701cd1e1914)
[C語言基礎及指針②之指針內存分析](http://www.jianshu.com/p/d556070b12ef)
[C語言基礎及指針③函數與二級指針](http://www.jianshu.com/p/184df8a1f195)
[C語言基礎及指針④函數指針](http://www.jianshu.com/p/181b50e02c89)
[C語言基礎及指針⑤動態內存分配](http://www.jianshu.com/p/93db7c692d1b)
[C語言基礎及指針⑥字符操作](http://www.jianshu.com/p/b7e6fc094087)
[C語言基礎及指針⑦結構體與指針](http://www.jianshu.com/p/36cc18151e87)
- 簡介
- C語言基礎及指針①語法基礎
- C語言基礎及指針②之指針內存分析
- C語言基礎及指針③函數與二級指針
- C語言基礎及指針④函數指針
- C語言基礎及指針⑤動態內存分配
- C語言基礎及指針⑥字符操作
- C語言基礎及指針⑦結構體與指針
- C語言基礎及指針⑧文件IO
- C語言基礎及指針⑨聯合體與枚舉
- C語言基礎及指針⑩預編譯及jni.h分析
- JNI開發系列①JNI概念及開發流程
- JNI開發系列②.h頭文件分析
- JNI開發系列③C語言調用Java字段與方法
- JNI開發系列④C語言調用構造方法
- JNI開發系列⑤對象引用的處理
- NDK開發基礎①使用Android Studio編寫NDK
- NDK開發基礎②文件加密解密與分割合并
- NDK開發基礎③增量更新之服務器端生成差分包
- C++基礎①命名空間結構體和引用