contributed by < uccuser159
>
使用 macro 可以在程式被編譯前就先處理定義的函式或數值,例如:
因為 linked list 要用到很多函式來執行一個 task ,所以適合使用 macro 來定義函式來增加執行效率。
Linux 應用 linked list 在哪些場合?舉三個案例並附上對應程式碼,需要解說,以及揣摩對應的考量
GNU extension 的 typeof 有何作用?在程式碼中扮演什麼角色
gcc manual [6.7] 提到 Another way to refer to the type of an expression is with typeof
typeof
會參考表示式的型態,其宣告方式有兩種:
With an expression
typeof (x[0](1))
假設 x 為陣列透過指標的方式傳入function中,則得到 function 回傳值的 type
With a type
typeof (int *)
得到的 type 是 pointers to int
因為macro本身沒辦法做型態檢查,只是單純的將值帶入並展開,使用 typeof 的話可以讓 macro 在不同 type 的變數皆可以使用,會變得更有彈性。
container_of
可以在 struct 中只知道某一 struct 成員的位址的情況下,抓出此 struct 的起始位址。例如:
根據上面的 struct ,若我們知道的是某個 student 的 phone_num,要找出此為 student 和 id ,就可以使用container_of
:
在 print_id
函式中, phone 即為某學生的電話,而container_of
做了以下這些事:
(type *) 0)->member
:
將 0 轉成指向 "student" 這個 struct 型態的 pointer,並將 poniter 指向 phone_num
__typeof__(((type *) 0)->member)
:
取得 phone_num 的 type
__typeof__(((type *) 0)->member) *__pmember
:
宣告一個型態為 phone_num 的指標 __pmember
__typeof__(((type *) 0)->member) *__pmember = (ptr)
:
__pmember 得到 phone 的位址
offsetof(type, member)
:
計算 struct 開頭到 phone_num 這個成員的偏移量
(type *) ((char *) __pmember - offsetof(type, member))
得到 struct 的起始位置,並轉成 "student" 這種 struct 型態
Reference
-Linux Kernel: container_of 巨集
除了你熟悉的 add 和 delete 操作,list.h 還定義一系列操作,為什麼呢?這些有什麼益處?
list.h 內都是 macro 或是 static inline 的宣告,都可以降低時間複雜度,讓執行效能增加,且可以簡化程式設計,像一個功能塊,例如想要檢查一個 linked list 是否為空的,就可以使用list_empty
,註解提到 Return: 0 - list is not empty !0 - list is empty
list_del()
中:表示當我們在刪除 linked list 的某個 node 時,因為此 node 只是脫離原本的 linked list,記憶體沒有被釋放掉,反而指向LIST_POISONING
這個位址,用意為防止讓程式設計者在已被移除的 node 再被用來執行 linked list 相關操作。
使用環狀 linked list 演算法較一般的 linked list 來的容易,彈性也較大,因為沒有第一個或是最後一個的問題,操作環狀 linked list 並不因為操作位置的不同而需要有不同的解決方法,例如list_del
並不會因為 node 的位置不同,而有不同的操作。
這兩個巨集都是走訪 linked list 用的,但是delete 這項操作只能在 list_for_each_safe 中:
由於 list_for_each_safe 會預先儲存當前 node 的下一個 node(safe node),所以即使在當回的迴圈中將 node 才 linked list 中移除,也可以繼續走訪到下一個節點(safe node)
for_each 這種風格的開發方式就像目前深度學習工具 Keras 一樣,有許多的API 可供程式開發者使用,可以把原本很複雜的東西用成一個 function 變的簡單易懂,從簡單到複雜,都一步步的指引與解釋。
unit test 的作用即是在測試每個 list.h 所定義的功能是否執行正確,以list_del.c
為例,即是在測試 list.h 的 list_del()
:
此精神即是"Divide and conquer",將 list.h 的每個 function 先個別拿出來做測試。
tests/ 目錄的 unit test 可如何持續精進和改善呢?