函數(shù)指針在Linux內(nèi)核和C語言開發(fā)中用的非常多,而且在設(shè)計(jì)操作系統(tǒng)的時(shí)候也會(huì)用到,因此這里將詳細(xì)講解函數(shù)指針。既然函數(shù)指針也是指針,那函數(shù)指針也占用4個(gè)字節(jié)(32位編譯器)。下面以一個(gè)簡單的例子說明:
#include
int add(int a,int b)
{
return a+b;
}
int main(int argc, char **argv)
{
int (*p)(int,int);
p=add;
printf("add(10,20)=%d\n",(*p)(10,20));
return 0;
}
函數(shù)指針的解引操作與普通的指針有點(diǎn)不一樣,對(duì)于普通的指針而言,解引只需要根據(jù)類型來取出數(shù)據(jù)即可,但函數(shù)指針是要調(diào)用一個(gè)函數(shù),其解引不可能是將數(shù)據(jù)取出,實(shí)際上函數(shù)指針的解引本質(zhì)上是執(zhí)行函數(shù)的過程,只是這個(gè)執(zhí)行函數(shù)是使用的call指令并不是之前的函數(shù),而是函數(shù)指針的值,即函數(shù)的地址。其實(shí)執(zhí)行函數(shù)的過程本質(zhì)上也是利用call指令來調(diào)用函數(shù)的地址,因此函數(shù)指針本質(zhì)上就是保存函數(shù)執(zhí)行過程的首地址。
為了確認(rèn)函數(shù)指針本質(zhì)上是傳遞給call指令一個(gè)函數(shù)的地址,下面用一個(gè)簡單例子說明:
上面是編譯后的匯編指令,可以看到,使用函數(shù)指針來調(diào)用函數(shù)時(shí),其匯編指令多了如下:
0x4015e3 mov DWORD PTR [esp+0xc],0x4015c0
0x4015eb mov eax,DWORD PTR [esp+0xc]
0x4015ef call eax
分析:第一行mov指令將立即數(shù)0x4015c0賦值給寄存器esp+0xc的地址內(nèi)存中,然后將寄存器esp+0xc地址的值賦值給寄存器eax(累加器),然后調(diào)用call指令,此時(shí)pc指針將會(huì)指向add函數(shù),而0x4015c0正好是函數(shù)add的首地址,這樣就完成了函數(shù)的調(diào)用。細(xì)心的讀者是否發(fā)現(xiàn)一個(gè)有趣的現(xiàn)象,上述過程中函數(shù)指針的值和參數(shù)一樣是被放在棧幀中,這樣看起來就是一個(gè)參數(shù)傳遞的過程,因此可以看到,函數(shù)指針最終還是以參數(shù)傳遞的形式傳遞給被調(diào)用的函數(shù),而這個(gè)傳遞的值正好是函數(shù)的首地址。
從上面可以看到函數(shù)指針并不是和一般的指針一樣可以操作內(nèi)存,因此作者覺得函數(shù)指針可以看作是函數(shù)的引用申明。
-
Linux
+關(guān)注
關(guān)注
87文章
11207瀏覽量
208716 -
C語言
+關(guān)注
關(guān)注
180文章
7594瀏覽量
135856 -
函數(shù)指針
+關(guān)注
關(guān)注
2文章
56瀏覽量
3770
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論