各人對于鏈表的使用并不是很頻繁,偶爾用一下,所以導致每次用都不記得怎么用了,都要重新分析一下邏輯,所以今天在這里記錄一下用法,方便自己也方便用得到的小伙伴查閱。
具體的函數接口這里就不介紹了,RTThread的API文檔里講的很清楚,按照API接口調用就可以了,比較容易。
這里主要說明rt_list_for_each_entry宏的用法,因為每次就這里不太好理解,這個宏實現的功能類似C++中用引用遍歷鏈表,很好用的。而且RTT已經給實現了這種遍歷方法如果不用總感覺自己虧了點啥
先看一下代碼里此宏的具體定義:
/**
rt_list_for_each_entry - iterate over list of given type @pos: the type * to use as a loop cursor.
@head: the head for your list.
@member: the name of the list_struct within the struct.
*/
#define rt_list_for_each_entry(pos, head, member)
for (pos = rt_list_entry((head)->next, typeof(*pos), member);
&pos->member != (head);
pos = rt_list_entry(pos->member.next, typeof(*pos), member))
乍一看可能有點亂,所以需要稍微梳理一下邏輯,梳理通了也就不復雜了。此宏具體的實現功能肯定是要遍歷鏈表內的每個節點成員,所以核心就是一個for循環,可每次要用這個宏的時候第一反應就是這個宏的三個參數是什么意思來著?要傳入什么?那就要先分析一下for信號里面的代碼了。
for循環相信大家都知道了,一般括號內有三條語句(有時把變化語句放到循環體內,這里就只有兩條語句了),第一條語句可以成為初始化語句,初始化循環變量。第二條語句是循環條件語句,為真則循環為假則退出循環。第三條語句是變量變化語句。
對應到這里的宏,第一條初始化語句為pos = rt_list_entry((head)->next, typeof(*pos), member);,是一個對pos的賦值語句,所以這里結合代碼和上面的注釋就能很容易知道第一個參數pos就類似普通for循環的循環變量。初始化又用到了另外一個宏rt_list_entry,此宏相關的代碼如下:
/**
@brief get the struct for this entry
@param node the entry point
@param type the type of structure
@param member the name of list in structure
/
#define rt_list_entry(node, type, member)
rt_container_of(node, type, member)
/ *
rt_container_of - return the member address of ptr, if the type of ptr is the
struct type.
*/
#define rt_container_of(ptr, type, member)
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
展開后就是一個減法計算:(char *)((head)->next) - (unsigned long)(&((typeof(*pos) *)0)->member),其中&((typeof(*pos) *)0)->member的功能是得到pos類型結構體內member成員的偏移地址。把0地址看做一個pos類型的結構體,再取其中任何成員的地址就自然是其偏移地址了。
所以這個宏的pos參數,傳入的應該是你自己定義的鏈表節點結構體指針,此結構體內包含一個rt_list_t類型的member成員變量。所以第三個參數傳入一個rt_list_t member變量即可。而第二個參數head傳入的是鏈表頭節點內的member變量指針。所以這里for循環內的第一條初始化語句就是初始化pos為鏈表內第一個節點的自定義結構體指針。
理解到這里,第二條語句就很容易理解了,就是判斷遍歷的pos內的下一個節點指針是不是又回到了head(單向鏈表里是判斷是否為NULL),是則已經遍歷一遍,退出循環。
第三條語句是取pos->member.next也就是下一個節點對于的自己定義結構體指針。
為了方便理解上面的內容,下面給出一個簡單的例子:
typedef struct __test_node
{
rt_uint16_t a; //可加入任何類型的用戶自定義變量
rt_uint16_t b;
rt_uint16_t c;
rt_list_t member;
}TestNode;
void rt_list_test()
{
TestNode test_head;
rt_list_init(&test_head.member);
for(int i = 0; i < 10; ++i) {
TestNode *new_node = rt_malloc(sizeof(TestNode));
new_node->a = i;
rt_list_insert_before(&test_head.member, &new_node->member);
}
rt_kprintf("list_len:%dn",rt_list_len(&test_head.member));
TestNode *list_pos;
rt_list_t member;
rt_list_for_each_entry(list_pos, &test_head.member, member)
{
rt_kprintf("a:%dn", list_pos->a);
}
}
運行結果:
-
減法器
+關注
關注
1文章
26瀏覽量
16826 -
C++語言
+關注
關注
0文章
147瀏覽量
6972 -
RTThread
+關注
關注
8文章
132瀏覽量
40811 -
for循環
+關注
關注
0文章
61瀏覽量
2493
發布評論請先 登錄
相關推薦
評論