C語言學習篇(18)-----函數指針

在上一節中我們詳細介紹了函數的組成部分,並逐一分析。相信大家都對函數有了更深一步的理解,這裡再次強調下函數的實質:是一段代碼,這一段代碼在內存中是連續分佈的,函數的第一句代碼(或函數名)就是函數的起始地址。

C語言學習篇(18)-----函數指針

函數指針


函數指針的實質

函數指針的實質還是指針(在32位系統中,所有的指針都是4字節,而在64位系統中,為8字節),與普通變量指針(如char *, int *),數組指針,結構體指針等都沒有本質區別。只是它的值是某個函數的地址,結合下圖理解:

C語言學習篇(18)-----函數指針

函數指針示意圖

函數指針的寫法和分析方法

因為C語言是強類型語言(即每一個變量都應申明其類型),編譯器並可根據其類型為我們做嚴格的檢查。譬如int類型指針就寫作int *p; 數組指針就寫作int (*p)[5](這個需要注意的是:如有一個int (*p2)[10],其中p2和p都是類型不兼容的,大家能想明白嘛?兩者雖然都是數組指針,指向的數組都是int類型,但是數組的長度不一致,即導致兩者的類型不同),這裡大家能感受到C語言編譯器檢查類型的嚴格之處的了吧~~

<code>#include <stdio.h>

int main(void)
{
\tint(*p)[5];
\tint (*p2)[10];
\t
\tp = p2;
\t
\treturn 0;
}/<stdio.h>/<code>

編譯警告:

C語言學習篇(18)-----函數指針

不兼容的指針類型

那麼我們的函數指針該如何書寫呢?這裡我列舉幾個函數,並分別寫出它們匹配的函數指針,以及通過函數指針來調用函數:

  • void func1(void)

對應的函數指針:void (*pFunc)(void); 具體代碼:

<code>#include <stdio.h>

void func1(void)
{
\tprintf("I am func1.\\n");
}

int main(void)
{
\tvoid (*pFunc)(void);
\t
\tpFunc = func1;\t\t\t
\t
\tpFunc();//我們通過函數指針調用函數
\t
\treturn 0;
}/<stdio.h>/<code>

運行結果:

C語言學習篇(18)-----函數指針

void (*pFunc)(void)

其中pFunc為函數指針,pFunc()表示用函數指針來調用其指向的函數。

特別說明的是:pFunc = &func1和pFunc = func1 效果是一樣的,這也是函數名和數組名最大的區別,函數名作為右值時,加不加&符號意義是一樣的,都是表示函數地址。

<code>pFunc = &func1;\t\t\t
pFunc();//我們通過函數指針調用函數/<code>

其運行結果與上圖一致!

  • char *strcpy(char *dest, const char *src)

這個是我們常常用的字符串拷貝函數,在<string.h>中定義, 我們現在就通過函數指針來調用。/<string.h>

其對應的函數指針類型:char * (*pFunc)((char *dest, const char *src) ,示例:

<code>#include <stdio.h>
#include <string.h>

int main(void)
{
\tchar a[20] = {0};
\tchar* (*pFunc)(char *, const char *);
\t
\tpFunc = strcpy;
\tpFunc(a, "hello world.");
\t
\tprintf("a = %s\\n", a);
\t
\treturn 0;

}/<string.h>/<stdio.h>/<code>

運行結果:

C語言學習篇(18)-----函數指針

char * (*pFunc)((char *dest, const char *src)

通過以上2個例子,大家是否能覺察到函數指針的寫法規律呢? 規律:函數返回值類型,和參數個數,參數類型都保持與要匹配的函數一致, 最後只要在變量前面加上符號*, 就大功告成拉。


分享到:


相關文章: