C函式指標

2021-09-01 11:35:53 字數 3870 閱讀 3764

c - 函式指標

1 簡介

c語言中,函式指標有著靈活和廣泛地用途(c++中,就更加的靈活了,這裡我們就先總結一下c中的用法),在這裡總結一下它的一些用法。函式**被載入在記憶體中後,也具有它的位址,即函式位址,函式指標是乙個指標變數,它的值可以指向某個函式的位址,在呼叫的時候,可以不通過函式名去呼叫了,直接通過函式指標來呼叫即可。

2 函式指標的使用

2.1 基本使用

c語言中,乙個函式指標變數的定義,正如 int a; 這樣定義乙個整型變數,定義乙個函式指標變數形式是:

returntype (*fun_ptr)(inputtype1 arg1, inputtype2 arg2, ...);
其中returntype是返回型別,inputtype是輸入引數的型別,比如double int char*等,比如定義乙個輸入引數為char*和int兩個引數,返回值為int的函式指標fun_ptr為:

int (*fun_ptr)(char*,int);

注意它的形式,比較怪異,函式指標變數名fun_ptr被包在乙個括號裡,前面還得加乙個*符號,後面再跟一對括號,括號裡分別列著輸入引數列表型別。定義後,這個fun_ptr就可以指向某個兩個輸入引數分別是char*和int,返回值是int的函式了。

#include void do_something(int num, char* str)

int main()

在上面的示例中,可以看出函式指標的賦值和使用,同時,我們看到6種函式呼叫的方法(invoke1~invoke6),可以看出c語言真是夠「靈活」。可以將函式名理解為函式的位址,然後其具有函式指標的屬性。invoke 1中,do_something這個函式,通過函式名去呼叫很好理解,平常也是這樣用的,然而它居然可以像invoke 2中可以通過(*do_something)這樣呼叫,其實我們可以這樣理解[1]:

do_something是乙個函式位址或者稱為函式指標;

do_something()的呼叫是(*do_something)()的簡寫形式;

&do_something是&(*do_something)的簡寫形式;

這樣一來,包括函式指標賦值的呼叫方式都好理解了,都以函式指標和其簡化形式來理解。在工程實踐中,我們在理解的基礎上選取一種風格就好了,弄的太多太雜沒有必要,否則就是故意為難自己和隊友,推薦使用簡單的invoke 3這種方式。

2.2 定義函式指標型別

每次定義乙個函式指標都用這麼繁雜的形式不太方便,我們可以用typedef來將其自定義為一種型別,比如:

typedef void(*funcptr)(int,char);
這樣funcptr就是乙個型別,宣告和定義乙個這類函式指標變數只需funcptr ptr;即可了,例如:

#include void do_something(int num, char b)

typedef void(*funcptr)(int,char); // type define

int main()

2.3 函式指標作為引數和返回值

當有函式指標變數作為引數和返回值時,形式就比剛才複雜一點兒了,比如定義乙個帶2個引數,返回值為int型別的函式指標,它2個引數中第乙個引數為乙個接收兩個int引數,無返回值的函式指標,第二個引數是乙個char*型別:

int (*func_ptr)(void (*)(int,int),char*);

寫法無非就是按照前面的函式指標定義的式子,核心就是將inputtype1擴充套件改寫為void (*)(int,int)這種函式指標宣告的形式。示例**如下:

#include void show_int(int a,int b)

int act_agency(void (*pfunc)(int,int),char* name)

int main()

函式指標作為返回值時,形式可能會和某些函式形式容易混淆,比如如下定義:

void (*func(int))();

注意,上述定義並非定義了乙個函式指標,而是宣告了乙個函式,這個函式帶有乙個int型引數,而返回值型別是乙個不帶引數,沒有返回值的函式指標,具體區分就在於函式指標定義形式裡面定義的是乙個變數名稱還是乙個函式還是乙個變數名稱,如果是乙個函式,則表示這個函式指標定義形式指的是這個函式的返回值,簡單來講:

int (*p)(); 

定義的是乙個函式指標p,p指向乙個不帶任何引數,返回值為int型的函式

int (*p())();

定義的是乙個函式p,該函式p不帶任何引數,返回值為乙個指向不帶任何引數,返回值為int型的函式指標

再以linux的系統api函式signal為例作示範,它的函式宣告為[2]:

#include void (*signal(int sig, void (*func)(int)))(int);

顯然,這是乙個函式,它有兩個引數,第乙個是int型的sig形參,第二個是乙個指向帶乙個int型別引數,無返回值的函式的函式指標,另外,它返回乙個帶乙個int型別引數無返回值的函式指標,可能有點拗口,但需要注意的是,這是在宣告乙個函式,而非定義乙個函式指標。

void * (*(*fp1)(int))[10];

float (*(*fp2)(int, int, float))(int);

typedef double (*(*(*fp3)())[10])();

fp3 a;

int (*(*fp4)[10])();

對於fp1:

我們從裡向外一點一點分析,首先(*fp1)(int),這說明fp1是乙個函式指標,它有乙個int型別的引數;

然後我們來找這個函式指標型別的返回值,注意到*(*fp1)(int),所以我們可以斷定它的返回值是乙個指標,

指標指向什麼呢?

我們可以看到最外層剩餘的部分是void* [10],因此這個函式的返回值是乙個指標,

這個指標指向乙個包含十個void*型別資料的陣列。

綜上:fp1是乙個函式指標,它所指向的函式有乙個int型別的引數,並且這個函式的返回值是乙個指標,

這個指標指向乙個包含10個void*元素的陣列。

對於fp2

就不再贅述了。fp2是乙個函式指標,它所指向的函式有三個引數,引數型別分別為int,int,float;

它的返回值是乙個函式指標,這個函式指標所指向的函式具有乙個int型別的引數,且返回型別為float。

對於fp3

fp3被定義為乙個函式指標型別,這種函式指標所指向的函式的引數為空;

它的返回值是乙個指標,這個指標指向乙個包含10元素的函式指標陣列,

這些函式指標所指向的函式的引數為空,返回值為double。

對於fp4

fp4是乙個指標,這個指標指向乙個包含10元素的函式指標陣列,

這些函式指標所指向的函式的引數為空,返回值為int。

其中,比較難以分析的複雜形式主要是摻合了陣列符號,由於c語言這種比如int a[20];這種將陣列符號「」放在變數名後面的風格讓這種定義晦澀難懂。我們需要根據函式指標形式和陣列符號的位置來進行分析其含義,我想,只有掌握了c語言語法編譯的原理才能完整掌握通用的分析方法,那咱們的工作就變成編譯器了。

所以,實際使用中多使用typedef來進行簡化,使得其清晰,越清晰簡單越好。如果實際工程實踐中真的出現需要這樣的定義,那咱們是不是得考慮**框架的問題了。

參考文獻

[1] 函式指標,

[2] linux程式設計(第4版)

C 指標函式和函式指標

1 指標函式 1 基本概念 指標函式 顧名思義就是帶有指標的函式,即其本質是乙個函式,只不過這種函式返回的是乙個對應型別的位址。2 定義式 type func type type 如 int max int x,int y 3 例子詳解 cpp view plain copy 1.include 2...

c 指標函式和函式指標

函式指標與指標函式 1 函式指標 形式 返回型別 函式名 參數列 一種特殊的指標,它指向函式的入口 定義乙個函式指標p,只能指向返回值為int,形參為兩個int的函式 輸出結果 include stdafx.h include using namespace std int p int,int in...

C 函式指標與指標函式

函式指標 函式名本身代表著函式的位址,因此給函數指標賦值使可以不用加 符號 加也可以!void func int 定義乙個函式 void pf int 定義乙個函式指標 pf func 給函式指標賦值 int f x,y 其中x,y是形式引數,f是函式名,呼叫後返回乙個指向整型資料的位址指標。f x...