1. 程式人生 > >深入理解C語言函式指標

深入理解C語言函式指標

我們一開始只是從功能上或者說從數學意義上理解myFun這個函式,知道myFun函式名代表的是一個功能(或是說一段程式碼)。函式名到底又是什麼東西呢?函式指標變數     一個數據變數的記憶體地址可以儲存在相應的指標變數中,函式的首地址也以儲存在某個函式指標變數中。這樣,我就可以通過這個函式指標變數來呼叫所指向的函數了。     在C系列語言中,任何一個變數,總是要先宣告,之後才能使用的。函式指標變數也應該要先宣告。     函式指標變數的宣告:     void (*funP)(int) ;   //宣告一個指向同樣引數、返回值的函式指標變數。    (整個函式指標變數的宣告格式如同函式myFun的宣告處一樣,只不過——我們把myFun改成(*funP)而已,這樣就有了一個能指向myFun函式的指標了。當然,這個funP指標變數也可以指向所有其它具有相同引數及返回值的函式。)示例2:
複製程式碼
#include <stdio.h>
#include <stdlib.h>

void (*funP)(int);   //宣告也可寫成void(*funP)(int x),但習慣上一般不這樣。
void (*funA)(int);
void myFun(int x);    //宣告也可寫成:void myFun( int );
int main()
{
    //一般的函式呼叫
    myFun(100);

    //myFun與funP的型別關係類似於int 與int *的關係。
    funP=&myFun;  //將myFun函式的地址賦給funP變數
    (*funP)(200
); //通過函式指標變數來呼叫函式 //myFun與funA的型別關係類似於int 與int 的關係。 funA=myFun; funA(300); //三個貌似錯亂的呼叫 funP(400); (*funA)(600); (*myFun)(1000); return 0; } void myFun(int x) { printf("myFun: %d\n",x); }
複製程式碼

輸出:

總結:1、 其實,myFun的函式名與funP、funA函式指標都是一樣的,即都是函式指標。myFun函式名是一個函式指標常量,而funP、funA是函式數指標變數,這是它們的關係。
2、但函式名呼叫如果都得如(*myFun)(10)這樣,那書寫與讀起來都是不方便和不習慣的。所以C語言的設計者們才會設計成又可允許myFun(10)這種形式地呼叫(這樣方便多了,並與數學中的函式形式一樣)。3、 為了統一呼叫方式,funP函式指標變數也可以funP(10)的形式來呼叫。4、賦值時,可以寫成funP=&myFun形式,也可以寫成funP=myFun。5、但是在宣告時,void myFun(int )不能寫成void (*myFun)(int )。void (*funP)(int )不能寫成void funP(int )。6、函式指標變數也可以存入一個數組內。陣列的宣告方法:int (*fArray[10]) ( int );示例3複製程式碼
#include <stdio.h>
#include <stdlib.h>

void (*funP)(int);
void (*funA)(int);
void myFun(int x);
int main()
{
    funP=&myFun;
    //深入理解
    printf("sizeof(myFun)=%d\n",sizeof(myFun));
    printf("sizeof(funP)=%d\n",sizeof(funP));
    printf("myFun\t 0x%p=0x%p\n",&myFun,myFun);
    printf("funP\t 0x%p=0x%p\n",&funP,funP);
    printf("funA\t 0x%p=0x%p\n",&funA,funA);
    return 0;
}

void myFun(int x)
{
    printf("myFun: %d\n",x);
}
複製程式碼

輸出:

總結:1、函式指標變數跟普通的指標一樣在32位系統下大小都為4。但是函式指標常量的大小為1.2、函式指標變數和函式指標常量儲存在記憶體的不同位置。3、為負值的函式指標變數(全域性)的值為0。函式指標作為某個函式的引數既然函式指標變數是一個變數,當然也可以作為某個函式的引數來使用的。示例:複製程式碼
#include <stdio.h>
#include <stdlib.h>

typedef void(*FunType)(int);
//前加一個typedef關鍵字,這樣就定義一個名為FunType函式指標型別,而不是一個FunType變數。
//形式同 typedef int* PINT;
void myFun(int x);
void hisFun(int x);
void herFun(int x);
void callFun(FunType fp,int x);
int main()
{
    callFun(myFun,100);//傳入函式指標常量,作為回撥函式
    callFun(hisFun,200);
    callFun(herFun,300);

    return 0;
}

void callFun(FunType fp,int x)
{
    fp(x);//通過fp的指標執行傳遞進來的函式,注意fp所指的函式有一個引數
}

void myFun(int x)
{
    printf("myFun: %d\n",x);
}
void hisFun(int x)
{
    printf("hisFun: %d\n",x);
}
void herFun(int x)
{
    printf("herFun: %d\n",x);
}
複製程式碼

輸出:

參考http://blog.pfan.cn/whyhappy/6030.html