contributed by < zack-404 >
以樹莓派藉由遠端控制進行此項作業唯一一個問題就是無法直接以提交所寫的程式碼至 Github ,目前尚未有 raspian 版本的 git-credential-manager 。目前以使用樹莓派進行測試,再藉由 Macbook Air 進行提交的動作。
工欲善其事,必先…
佇列為一種先進先出的資料結構,此次實作注重其與鏈結串列的關係。
inline
對函式效能的影響在參閱 25077757 與 nosba0957 的程式碼時,發現 25077757 在諸多函式加入了 static
與 inline
兩個關鍵字。
static
關鍵字在 C 語言If the declaration of a file scope identifier for an object or a function contains the storageclass specifier static, the identifier has internal linkage.(22) (C99 6.2.2)
(22) A function declaration can contain the storage-class specifier static only if it is at file scope; see 6.7.1. (C99 6.2.2)
In addition to optional type qualifiers and the keyword
static
, the [ and ] may delimit an expression or*
. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function
type. The optional type qualifiers and the keywordstatic
shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation (C99 6.7.5.2)
查閱 C 語言規格書,不要把自己的專業前途交給你沒有注入資本的大語言模型。
優先閱讀權威材料!
inline
A function declared with an inline function specifier is an inline function. The
function specifier may appear more than once; the behavior is the same as if it appeared
only once. Making a function an inline function suggests that calls to the function be as
fast as possible.(118) The extent to which such suggestions are effective is
implementation-defined.(119) (C99 6.7.4.5)
Any function with internal linkage can be an inline function. For a function with external
linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the
file scope declarations for a function in a translation unit include the inline function
specifier without extern, then the definition in that translation unit is an inline
definition. An inline definition does not provide an external definition for the function,
and does not forbid an external definition in another translation unit. An inline definition
provides an alternative to an external definition, which a translator may use to implement
any call to the function in the same translation unit. It is unspecified whether a call to the
function uses the inline definition or the external definition.120) (C99 6.7.4.5)
elememt_t
與 queue_contest_t
由上述程式碼與註解可知, list_head
提供一個雙向鏈結串列的單元結構。
element_t
中的 *value
則是在記錄該結點的值,而 list
則是記錄串列中相鄰的兩個節點。
而queue_context_t
與 element_t
不同的地方在於它可以記錄的不單單是一個節點,而可以是串列中的一個子串列。 size
與 id
則分別紀錄此子串列的大小與 id
。
q_new
q_free
此函式目標為清除佇列上所有的節點。
以上為 list.h
所提供的 API ,用途為持續進行 node->next
直到 node
與 (head)
相同。若 node
與 (head)
相同,則代表 head
與 tail
相同,意即為空的佇列。
首先,要先確認 head
是否為空指標。若為空指標,則此佇列以為空佇列,不用繼續執行後續程式。若非空指標,則藉由 list.h
提供的 list_for_each_safe
與 queue.h
提供的 q_release_element
走訪與刪除節點,最後就可以完成清空佇列的動作。
q_insert_head
與 q_insert_tail
q_insert_head
目標為在佇列的前端插入一個節點並回傳布林值確認是否成功插入,而 q_insert_tail
則目標插入節點於最末端。不過兩者的實作皆須注意是否為 head
與tail
。此外,此兩項實作亦可與通用的 q_insert
結合,進而精簡程式碼。以下實作將注重於實作通用的 q_insert
。
q_remove_head
與 q_remove_tail
container_of
巨集用於計算共有幾個結構的指標有包含指標 ptr
。
strncpy
函式用於複製字串,特別之處在於能夠使用空值字元 '\0'
填補省略空缺,其取決於字串長度。
要刪除整個佇列的 head
或 tail
,此行為即為刪除此佇列開頭的
q_size
此函式的目的在於回傳目前佇列的長度。
上述 list.h
所提供的 list_for_each
API 使用與 list_for_each_safe
相同的技巧走訪佇列中的每個節點,直到 head
與 tail
相同,即走訪完成。
註:在 linux 中,鏈結串列為雙向且環狀
實作以 list_for_each
API 為基底,以 len
紀錄共走訪了幾步。
q_delete_mid
q_delete_dup
首先, del
與 remove
最大的差別在於被刪除的節點是否會繼續存在於記憶體。在串列中 del
就是將該節點與前後節點斷開,但該節點仍存在於記憶體;而remove
則是將該節點於記憶體中抹除,釋放記憶體空間。
list_splice
join or connect (a rope or ropes) by interweaving the strands at the ends.
swap
鏈結串列是一個環狀的結構,所以只要拆開其中一個,並把他的 next
與 prev
接上 first
與 last
;因其是雙向的,所以最後還要再用一次。 delete
會用到。
q_reverse
reverse
最直觀的觀點就是走訪每個節點,並把節點中的 prev
與 next
對調,不過實作中必須注意是否能夠走訪每個節點。
實作中,藉由 list_move
的 API 完成更新節點的步驟;而 list_add
API 則包含了交換 prev
與 next
的步驟。
q_reverseK
此項函式與 q_reverse
不同的地方在於 q_reverseK
轉置的不是一個節點,而是連續 K 個節點。
poat 才有順序
?