1. 程式人生 > >C語言基礎及指標④函式指標

C語言基礎及指標④函式指標

接續上篇C語言基礎及指標③函式與二級指標

在上一篇中 , 我們學習了函式與二級指標 , 函式和java中的方法類似 , 只是缺少了訪問控制符 , 二級指標也就是指標的指標 , 指標裡面儲存的是指標的地址 , 可以通過*操作符不斷往上追溯 , 然後通過記憶體地址操作記憶體空間 。

函式指標

當我們定義一個函式的時候 , 這個函式也會像變數一樣 , 會有一個記憶體地址 , 我們也可以將函式定義成為一個函式指標 , 但函式不同於變數 , 變數儲存的是固定的值 , 而函式指標儲存的是函式的記憶體地址 。下面我就用一個示例來說明:

// windows 彈出框標頭檔案
#include <Windows.h>

/*函式*/
void message() {
    MessageBox(NULL, "我是彈出框", "訊息", NULL);
}

void main() {

    // 函式指標定義 , 返回值(函式指標名稱)(函式引數) = 函式名稱
    void(*func_p)() = &message;

    // 呼叫函式指標
    func_p();

    printf("函式指標地址:%#x\n", func_p);

      getchar();
}

輸出:

函式指標地址:0xe6d31073

我們可以通過函式指標地址 , 反彙編我們的程式設計師 , 檢視他的跳轉

函式指標彙編1.png

 

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

函式指標彙編2.png

 

我們看到通過函式指標裡面儲存的是一個函式的地址 ,然後通過一個jmp指令調到我們的函式定義執行 。

有了我們的函式指標 , 我們可以做很多事情 , 下面我們來看一個簡單的示例:

  
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();


輸出:

計算完成=20
計算完成=28

通過傳入函式地址 , 就可以呼叫函式進行運算 , 我們只要按照傳入的引數和返回值 , 寫我們自己的函式 , 通過這個方法 , 我們就可以統一的實現我們函式的功能 。下面我們來寫一個回撥函式:

/*模擬網路請求回撥*/
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);
}

輸出:

請求地址:www.zhuyongit.com , 正在請求網路....
網路請求回撥
請求到的資料:我是請求的網路資料 , 落花有意隨流水 , 流水無情戀落花

我們模擬了網路請求的常見封裝 , 使用一個回撥函式來接收我們請求回來的資料 。函式指標很強大 , 我們可以直接傳入函式名稱 , 再另一個函式裡面執行我們傳入的函式 , 如果是在java裡面 ,我還需要傳入一個物件 , 再通過物件來呼叫方法 , 在C語言裡面 , 直接通過函式指標就可以搞定 。



作者:逝我
連結:https://www.jianshu.com/p/181b50e02c89
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。