# 2018q3 Homework3 (list) contributed by <[`yungchuan`](https://github.com/yungchuan)> ## 自我檢查事項 ### 為何 Linux 採用 macro 來實作 linked list?一般的 function call 有何成本? 因為 macro 的概念是展開,在前處理的時候就會把程式碼中用到 macro 的地方替換成需要的程式碼。不用 function call 的原因是因為 function call 會需要額外的空間儲存一些 local variable 以及 return address 等資料,此為 function call 的成本。 ### Linux 應用 linked list 在哪些場合?舉三個案例並附上對應程式碼,需要解說,以及揣摩對應的考量 待補 ### GNU extension 的 typeof 有何作用?在程式碼中扮演什麼角色? typeof 顧名思義就是取得變數的型態,它的用法主要就是用以有的變數型態宣告新的變數,如以下 ```C int x; typeof (x) a; typeof (&x) b; typeof (int) c; ``` 上述的 a 的型態為 int 、 b 為 int * 、 c 為 int , typeof 方便在於可以在不知道某變數的型態的情況下,宣告一樣型態的變數。 ### 解釋以下巨集的原理 ```C= #define container_of(ptr, type, member) \ __extension__({ \ const __typeof__(((type *) 0)->member) *__pmember = (ptr); \ (type *) ((char *) __pmember - offsetof(type, member)); \ }) ``` * 定義了一個 container_of 的巨集,當中有參數 ptr, type, member。 * `__extension__` 代表讓編譯器忽略後面的錯誤,當中的 `__typeof__` 是 gnu 編譯器的功能,若在編譯的時候加上 std=c99 之類的規格設定,可能會導致錯誤,而 `__extension__` 可以避免這類錯誤訊息。 * ptr, type, member 為使用句集時會傳入的參數,在第 3 行中,從 (type *) 0 可以猜測 type 為一種型態,如此把 0 轉型成 type 的指標,而從後面接著 `->member` 可以進一步的確認 type 為一個結構型態,包含了一個成員,型態為 member 。 * 所以第 3 行代表:使用 type 結構中的成員 member 的型態的指標定義一個變數`__pmember` ,內容為傳入此巨集的參數 ptr ,由此可知 ptr 應為一位址或指標變數。 * 第 4 行用 offsetof 找出 type 與 member 之間的記憶位移量,而由第 3 行知道 `__pmember` 是某個 type struct 裡的 member 的記憶體位址,所以只要用此記憶體位址減去 type 與 member 的 offset 就可以得知此 `__pmember` 所屬的 type struct 的位址。 ### 除了你熟悉的 add 和 delete 操作,`list.h` 還定義一系列操作,為什麼呢?這些有什麼益處? 除了 add 和 delete 操作以外, `list.h` 還定義了許多操作,像 `list_splice, list_cut_position` 等。而這些操作可以使得我們更方便的操作 linked list ,像是要在 linked list 中直接插入另一條 linked list ,若只有 add function 會很麻煩,而且缺乏效率。還有若是已經知道要插入的位置,但是還是要再從頭搜尋到此位置也是很沒效率的,而 `list.h` 也提供可以直接進行操作的函式,簡單來說, `list.h` 在某些情況下可以大幅提昇效能。 ### `LIST_POISONING` 這樣的設計有何意義? 待補 ### linked list 採用環狀是基於哪些考量? * 可以快速的對尾端進行操作。 * 若操作不慎使得中間的 link 斷開,有機會復原。 * 可以實做一些環狀或是沒有明確頭尾的資料結構。 ### `list_for_each_safe` 和 `list_for_each` 的差異在哪?“safe” 在執行時期的影響為何? * `list_for_each` 使用一個迴圈對 list 的每一個 node 進行操作,但是這個操作如果有更動到 node 的 next ,那下一個進行操作的就是新的 next node。 * 如果使用的是 `list_for_each_safe` ,則使用了一個 safe node 幫助記錄 next node ,因此若更動到 node 的 next ,下一個操作的一樣是原本的 next。也就是說 `list.h` 提供了兩個 `for_each` 的函式,可以視需求選用。 ### for_each 風格的開發方式對程式開發者的影響為何? 開發者必須慎重的確認是否要對 list 的每個 node 都進行操作,若此操作影響到 list 的順序那又應該要注意哪些細節,選用哪種操作方式。也就是說,即使提供了方便的工具,開發者還是要仔細想清楚執行結果與預期結果是否相符。 ### 程式註解裡頭大量存在 `@` 符號,這有何意義?你能否應用在後續的程式開發呢? 這些在註解中的 @ 符號,代表程式碼中變數的名字,很多時候為了程式的可讀性變數名稱會取很常見的單字,如果不加 @ 符號的話,很有可能會誤會成單字本身的意思。所以程式碼註解中加上 @ 符號可以幫助區隔是提到變數本身還是只是單純句子中的單字。 ### `tests/` 目錄底下的 unit test 的作用為何?就軟體工程來說的精神為何? 待補 ### `tests/` 目錄的 unit test 可如何持續精進和改善呢? 待補