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