上文分享了一個專用的雙鍊表的基本操作示例:雙鍊表的基本操作
這裡提到了一個關鍵詞:專用。與專用對應的詞是通用。我們從字面上可以很容易理解這兩個詞,專用就是針對特定情況的,特點就是很有局限性;通用就是可以針對大多數情況(更理想的就是所有情況),特點就是适用性廣。
為什麼說上篇筆記的雙鍊表是專用的?
從我們的定義的元素數據類型就可以知道,我們這個雙鍊表是隻是用來存儲int類型的數據的,這就很能體現出了局限性(這隻是其中一點,當然還有其它的很多局限性),因此是個專用的雙鍊表。
我們要編寫一個通用的雙鍊表的話,我們首先要做的是就是修改雙鍊表結點結構體了,可以修改為:
如果我們要存放整數,我們可以把void*強制轉換成整數使用。當然這篇筆記的重點不是分享通用的雙鍊表。我們這篇筆記要分享的是回調函數,下面進入重點内容:
我們上篇筆記中有一個打印輸出鍊表數據的函數:
這是我們這個專用的雙鍊表中打印鍊表數據函數,我們存儲的是整數,所以用%d打印。那麼,如果我們面向的是通用的雙鍊表呢?我們無法預知其中的數據,可能是整數,也可能是字符串,或者是其它的數據。那麼怎麼辦呢?這裡有幾種方法:
方法一:實現多個函數,需要用到哪個就調哪個
比如存放的是整數,可以調用dlist_print_int函數來打印;存放的是字符串,可以調用dlist_print_string函數來打印。
這種方法很簡單,但有個缺點:每個函數都很相似,會有大量重複的代碼。
方法二:傳入一個附加的參數來選擇打印的方式
這種方法使用一個參數來選擇打印的方式。避免了方法一中産生大量重複的代碼的問題。但是我們每當要增加新類型時,都得修改這個dlist_print函數,對于一個通用的雙鍊表來說,這樣的修改是不夠好的。這裡dlist_print函數也是通用雙鍊表的一部分,我們應該盡量少去修改它。
假如我們把一個通用的雙鍊表的基礎操作比喻做一棟樓房的地基,地基一旦牢牢固固的搭好之後,我們就不要再去動它了, 應該把精力放在如何搭建房子的上層上。
方法三:回調函數法
上面兩種方法應該是很容易想到的方法。現在來分享我們可能想不到的方法——回調函數法,這也是本篇筆記要分享的重點。
可能有很多朋友沒用過回調函數,甚至有些朋友都沒聽說過。這裡先簡單介紹回調函數的一些概念(以下概念來自百度百科):
回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。
回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。
知識點:變量指針指向的是一塊數據,指針指向不同的變量,則取到的是不同的數據;函數指針指向的是一段代碼(即函數),指針指向不同的函數,則具有不同的行為。
回歸正題,下面看如何使用回調函數法來實現上面的需求。
首先,我們需要實現一個通用的打印函數dlist_print,把函數指針變量作為其中一個參數傳入。其次,我們調用者得根據實際情況實現一個用于打印的回調函數,這裡我們實現的的回調函數是dlist_print_int。最後,在用到打印的地方調用dlist_print函數即可。
用回調函數法是不是很巧妙?
此處,我們用到了typedef來“封裝”一個打印鍊表數據的函數指針類型,這可能會刷新了初學者對于typedef關鍵字的認識。因為我們剛開始學C語言的時候,總認為typedef取别名的一般形式為:
typedef 舊名字 新名字;
确實也是這樣,但遇到給函數指針類型、數組類型等定義别名的時候就要特别區分了。如:
typedef char ARRAY20[20];
ARRAY20 a1,a2; /* 等價于char a1[20],a2[20]; */
别問我為什麼,就是這樣的。。。
上面分析了那麼多,可能很多朋友會覺得回調函數太麻煩了,沒必要用。但是現實是,回調函數在我們的C編程、嵌入式編程中用得很廣泛。
1、在C編程中
在C語言的通用工具庫stdlib.h中,有如下一個函數原型:
void qsort(void *, size_t, size_t, int (comp*)(const void *, const void *));
這是在C通用工具庫中聲明的一個快速排序算法函數,其可以用來排序int類型、float類型以及字符串數據,可以按從小到大的順序也可以按從大到小的順序排序。其關鍵在于函數指針comp指向的函數的具體實現。
2、在嵌入式編程中
我們之前的筆記:【RT-Thread筆記】PIN設備中斷配置中,就有用到回調函數。RT-Thread給我們提供了PIN設備中斷回調綁定函數:rt_pin_attach_irq
這是個中斷實驗,産生中斷會回調我們的回調函數,所以可以在在我們的回調函數裡做一些産生中斷後需要做的操作。比如我們在這個中斷回調裡打印一串字符串。每當中斷來時,就會打印該字符串:
回調函數是一個很重要的知識點,我們需要掌握。而回調函數又與函數指針聯系密切,我們要努力把函數指針弄懂、用熟。在C語言中,指針很重要,函數指針更重要。正如前輩們常說類似這樣子的話:不會C指針,就沒學會C語言;不會函數指針,就不要稱自己是C語言高手。
在這幾種方法中的分析中,其實回調函數更多的是體現出了軟件分層的思想。分層思想在我們軟件開發中是一種很重要的思想,簡單的分層我們都會,但是怎麼才能算是分層分得很好呢?那就是不該動的地方不動,該動的地方才動,銜接得很好,就像上面的回調函數法。
對于編程的學習,關于編程語言的學習,知識點就那麼一點,很快就能學完了,但是真正靈活的、熟練應用起來真的是不容易,這需要我們大量地分析、思考、練習。有時間的話我們也應該多讀讀一些關于軟件設計思想的書籍,這也是我最近在讀的一類書,學學前輩們總結出的一些精華知識。
以上就是本次關于回調函數的筆記分享,如有錯誤,歡迎指出。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!