深入理解C語言函數指針


示例1:

void myFun(int x);    //聲明也可寫成:void myFun( int );
int main()
{
    myFun(100);//一般的函數調用
    return 0;
}
void myFun(int x)
{
    printf("myFun: %d\n",x);
}
我們一開始只是從功能上或者說從數學意義上理解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
 
(轉載請注明出處 ^.^)
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM