指向成員函式的指標有什麼用 高階指標話題 函式指標

2021-10-11 13:31:09 字數 3367 閱讀 2935

函式指標是什麼?如何使用函式指標?函式指標到底有什麼大用?本文將一一介紹。

#include int test()

int main(void)

編譯:

gcc -o testfun testfun.c

$ nm testfun |grep test  #檢視test函式的符號表資訊

0000000000400526 t test

宣告普通型別指標時,需要指明指標所指向的資料型別,而宣告函式指標時,也就要指明指標所指向的函式型別,即需要指明函式的返回型別和形參型別。例如對於下面的函式原型:

int sum(int,int);

它是乙個返回值為int型別,引數是兩個int型別的函式,那麼如何宣告該型別函式的指標呢?很簡單,將函式名替換成(*pf)形式即可,即我們把sum替換成(*fp)即可,fp為函式指標名,結果如下:

int (*fp)(int,int);

這樣就宣告了和sum函式型別相同的函式指標fp。這裡說明兩點,第一,*和fp為一體,說明了fp為指標型別,第二,*fp需要用括號括起來,否則就會變成下面的情況:

int *fp(int,int);

這種情況下,意思就大相徑庭了,它宣告了乙個引數為兩個int型別,返回值為int型別的指標的函式,而不再是乙個函式指標了。

在經常使用函式指標之後,我們很快就會發現,每次宣告函式指標都要帶上長長的形參和返回值,非常不便。這個時候,我們應該想到使用typedef,即為某型別的函式指標起乙個別名,使用起來就方便許多了。例如,對於前面提到的函式可以使用下面的方式宣告:

typedef int (*myfun)(int,int);//為該函式指標型別起乙個新的名字

myfun f1; //宣告myfun型別的函式指標f1

上面的myfun就是乙個函式指標型別,在其他地方就可以很方便地用來宣告變數了。typedef的使用不在本文的討論範圍,但是特別強調一句,typedef中宣告的型別在變數名的位置出現,理解了這一句,也就很容易使用typedef了。因而下面的方式是錯誤的:

typedef myfun (int)(int,int);   //錯誤

typedef (int)(int,int) *myfun; //錯誤

賦值也很簡單,既然是指標,將對應指標型別賦給它既可。例如:

#includeint test(int a,int b)

typedef int(*fp)(int,int);

int main(void)

在這裡,宣告了返回型別為int,接受兩個int型別引數的函式指標f1和f2,分別給它們進行了賦值。表示式1和表示式2在作用上並沒有什麼區別。因為函式名在被使用時總是由編譯器把它轉換為函式指標,而前面加上&不過顯式的說明了這一點罷了。

呼叫也很容易,把它看成乙個普通的函式名即可:

#includeint test(int a,int b)

typedef int(*fp)(int,int);

int main(void)

在函式指標後面加括號,並傳入引數即可呼叫,其中表示式1和表示式2似乎都可以成功呼叫,但是哪個是正確的呢?ansi c認為這兩種形式等價。

函式指標的應用場景比較多,以庫函式qsort排序函式為例,它的原型如下:

void qsort(void *base,size_t nmemb,size_t size , int(*compar)(const void *,const void *));

看起來很複雜對不對?拆開來看如下:

void qsort(void *base, size_t nmemb, size_t size, );

拿掉第四個引數後,很容易理解,它是乙個無返回值的函式,接受4個引數,第乙個是void*型別,代表原始陣列,第二個是size_t型別,代表資料數量,第三個是size_t型別,代表單個資料占用空間大小,而第四個引數是函式指標。這第四個引數,即函式指標指向的是什麼型別呢?

int(*compar)(const void *,const void *)

很顯然,這是乙個接受兩個const void*型別入參,返回值為int的函式指標。

到這裡也就很清楚了。這個引數告訴qsort,應該使用哪個函式來比較元素,即只要我們告訴qsort比較大小的規則,它就可以幫我們對任意資料型別的陣列進行排序。

我們通過乙個例項來看函式指標怎麼使用。假設有一學生資訊,需要按照學生成績進行排序,該如何處理呢?

#include #include #define stu_name_len 16

/*學生資訊*/

typedef struct student_tag

student_t;

int studentcompare(const void *stu1,const void *stu2)

int main(void)

; student_t stu2 = ;

student_t stu3 = ;

student_t stu = ;

/*排序,將studentcompare作為引數傳入qsort*/

qsort((void*)stu,3,sizeof(student_t),studentcompare);

int loop = 0;

/**遍歷輸出*/

for(loop = 0; loop < 3;loop++)

return 0;

}

我們建立了乙個學生資訊結構,結構成員包括名字,學號和成績。main函式中建立了乙個包含三個學生資訊的陣列,並使用qsort函式對陣列按照學生成績進行排序。qsort函式第四個引數是函式指標,因此我們需要傳入乙個函式指標,並且這個函式指標的入參是cont void *型別,返回值為int。我們通過前面的學習知道了函式名本身就是指標,因此只需要將我們自己實現的studentcompare作為引數傳入即可。

最終執行結果如下:

name:two,id:2,score:77

name:three,id:3,score:88

name:one,id:1,score:99

可以看到,最終學生資訊按照分數從低到高輸出。

指標的指標有什麼用

指標的用處我知道 比如 int p 3 int x p x作為p的索引 那麼指標的指標呢,既然它出現在c中肯定有用,可是我實在不知道有什麼用,難道對指標進行索引,索引的索引?答 我給樓主乙個最直接的理由 那就是如果你希望在乙個函式的引數中改變乙個指標的值,你就只能傳這個指標的指標給這個函式。比如有i...

單鏈表為什麼用指向指標的指標

int a 1,b 2 void change int x void change int x void main 上面的例子很好的說明了傳遞指標與傳遞指標的指標的不同 所以在建立單鏈表時,由於需要修改傳遞給呼叫函式的頭指標的值,所以需要傳遞指向頭指標的指標 include include incl...

函式型別有什麼用?

函式型別通常用來宣告函式或者用來組成複雜的型別,例如 void foo c c 規定函式的返回值不能是函式型別或者陣列型別,只能用函式指標或者物件指標 來代替例如,有如下宣告 typedef int f void 這種型別的函式不帶引數,返回值是int。那麼可以這樣宣告f和g f f,g 相當於宣告...