您好,登錄后才能下訂單哦!
在C語言中:指針是C語言的特色,有著各種各樣的指針,普通的變量指針,常量指針,數(shù)組指針,指針數(shù)組,函數(shù)指針,指針函數(shù)。我們就講一下函數(shù)指針與回調(diào)函數(shù)吧
首先關(guān)于函數(shù)指針,其實(shí)很簡單。
對于一個函數(shù)指針來說,顧名思義,就是一個指向函數(shù)的指針,需要知道的是,對于指針而言,他總是存儲一塊地址,地址里面有著一個,一組,或者一塊數(shù)據(jù),在函數(shù)中,函數(shù)的存儲是放在代碼段的,每個函數(shù)都有著一個函數(shù)首地址,調(diào)用了這個地址相當(dāng)于調(diào)用的這個函數(shù)。
具體的可以觀看我的這篇博客,其中就通過在內(nèi)存階段改變棧幀返回值,成功的調(diào)用了一個重啟函數(shù)。淺談棧幀(一)
其實(shí)C++特性中的虛函數(shù)表就有利用這一點(diǎn)。
所以說呢,函數(shù)指針就是一個指向函數(shù)首地址的指針,好了,先了解這個定義,然后我們進(jìn)入下一個階段。
對于指針,他不僅僅要指向一個具體的量,他還需要其他的標(biāo)識符來描述這個量的具體屬性。
例如:char* str,void *func(int,int);
在指針符號*的左右,都是在描述這個指針的具體信息。
那么對于函數(shù)指針而言,這是怎么樣的呢。
void (*f) ( );雖然()的優(yōu)先級高于*,但由于有括號存在,首先執(zhí)行的是解引用,所以f是一個指針;接下來執(zhí)行( ),表明f指向一個函數(shù),這個函數(shù)不返回任何值?,F(xiàn)在得出結(jié)論:f是一個指向不接受參數(shù)且不返回任何值的函數(shù)的指針,簡稱函數(shù)指針(pointer to function)。
<1>.初始化
注意指向函數(shù)的指針(函數(shù)指針)指向的是函數(shù)而非普通的變量,它所指向的函數(shù)也是有特定類型的,函數(shù)的類型由它的返回值類型以及形參列表確定,和函數(shù)名無關(guān)。對函數(shù)指針初始化時可以采用相同類型函數(shù)的函數(shù)名或函數(shù)指針(當(dāng)然還有零指針常量)。假如有函數(shù)void test ( ),int wrong_match (int)和函數(shù)指針void (*ptf) ( )。
下面的初始化是錯誤的,因?yàn)楹瘮?shù)指針的類型與函數(shù)的類型不匹配:
f = wrong_match;
f = & wrong_match;
ptf = wrong_match;
ptf = & wrong_match;
以下初始化及賦值是合法的:
f = test;
f = &test;
ptf = test;
ptf = &test;
f = pf;
要做出解釋的是test和&test都可以用來初始化函數(shù)指針。C語言規(guī)定函數(shù)名會被轉(zhuǎn)換為指向這個函數(shù)的指針,除非這個函數(shù)名作為& 操作符或sizeof操作符的操作數(shù)(注意:函數(shù)名用于sizeof的操作數(shù)是非法的)。也就是說f = test;中test被自動轉(zhuǎn)換為&test,而f= &test;中已經(jīng)顯示使用了&test,所以test就不會再發(fā)生轉(zhuǎn)換了。因此直接引用函數(shù)名等效于在函數(shù)名上應(yīng)用 & 運(yùn)算符,兩種方法都會得到指向該函數(shù)的指針。
int (*function(int)) (double*,char);要了解此聲明的含義,首先來看function(int),將function聲明為一個函數(shù),它帶有一個int型的形式參數(shù),這個函數(shù)的返回值為一個指針,正是我們本將開頭講過的函數(shù)指針int (*) (double*, char);這個指針指向一個函數(shù),此函數(shù)返回int型并帶有兩個分別是double*型和char型的形參。如果使用typedef可以將這個聲明簡化:
typedef int (*ptf) (double*, char);
ptf function(int );
總結(jié):
其實(shí)對于函數(shù)指針來說。我們只需要記住。從最中間括號開始往外逐步分析,函數(shù)指針是(*)
而指針函數(shù)是(*()),懂得會分區(qū),就知道函數(shù)指針是什么東西了。弄清楚他本身名字,然后弄清楚他的描述情況。
回調(diào)函數(shù):
上面已經(jīng)說清楚了對于函數(shù)指針而言,他有著他自己的名字,有著相對于的描述信息,信息不一樣的無法進(jìn)行賦值配對,然后既然有函數(shù)指針這種東西?那么他出現(xiàn)是干什么用的呢?
其實(shí)對于函數(shù)指針,無非就是讓我們在面臨不同情況去使用他。函數(shù)指針指向不同的情況,來進(jìn)行不同的操作,在主題函數(shù)處理中提供不同的函數(shù)指針借口,借此來處理不同的情況。
在計(jì)算機(jī)程序設(shè)計(jì)中,回調(diào)函數(shù),或簡稱回調(diào)(Callback 即call then back 被主函數(shù)調(diào)用運(yùn)算后會返回主函數(shù)),是指通過函數(shù)參數(shù)傳遞到其它代碼的,某一塊可執(zhí)行代碼的引用。這一設(shè)計(jì)允許了底層代碼調(diào)用在高層定義的子程序。
來看一個簡單例子:
#include <stdio.h> int int_cmp(const void * p1, const void * p2) { if (*( int *)p1 > *(int *) p2) { return 1; } else if (*( int *)p1 == *(int *) p2) { return 0; } else { return -1; } } void _swap(void *p1, void * p2, int size) { int i = 0; for (i = 0; i< size; i++) { char tmp = *((char *)p1 + i); *(( char *)p1 + i) = *((char *) p2 + i); *(( char *)p2 + i) = tmp; } } void bubble(void *base, int count , int size, int(*cmp )(void *, void *)) { int i = 0; int j = 0; for (i = 0; i< count - 1; i++) { for (j = 0; j<count - i - 1; j++) { if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0) { _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size); } } } } int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; //char *arr[] = {"aaaa","dddd","cccc","bbbb"}; int i = 0; bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp); for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++) { printf( "%d ", arr[i]); } printf("\n"); return 0; }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。