精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于rtthread內鏈表rt_list_for_each_entry的用法

冬至子 ? 來源:吉利咕嚕2022 ? 作者:吉利咕嚕2022 ? 2023-08-07 15:17 ? 次閱讀

各人對于鏈表的使用并不是很頻繁,偶爾用一下,所以導致每次用都不記得怎么用了,都要重新分析一下邏輯,所以今天在這里記錄一下用法,方便自己也方便用得到的小伙伴查閱。

具體的函數接口這里就不介紹了,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.jpg

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 減法器
    +關注

    關注

    1

    文章

    26

    瀏覽量

    16826
  • C++語言
    +關注

    關注

    0

    文章

    147

    瀏覽量

    6972
  • RTThread
    +關注

    關注

    8

    文章

    132

    瀏覽量

    40811
  • for循環
    +關注

    關注

    0

    文章

    61

    瀏覽量

    2493
收藏 人收藏

    評論

    相關推薦

    【Linux高級編譯】list.h的高效應用—雙向鏈表的實現

    【Linux高級編譯】Linux內核的list.h的高效應用——雙向鏈表的實現
    的頭像 發表于 09-15 10:00 ?2558次閱讀
    【Linux高級編譯】<b class='flag-5'>list</b>.h的高效應用—雙向<b class='flag-5'>鏈表</b>的實現

    rtthread 5.20安裝systemview 2.52a出錯的原因?

    rt_thread\' thread = rt_list_entry(node, struct rt_thread, list); 提示 packages/SystemView
    發表于 07-12 09:36

    Linux內核的鏈表操作

    = list_entry(i, struct nf_sockopt_ops, list); 大多數情況下,遍歷鏈表的時候都需要獲得鏈表節點數據項,也就是說
    發表于 08-29 11:13

    Linux Kernel數據結構:鏈表

    連接起來,形成鏈表,通過通用的鏈表函數來進行操作。有點可想而知,這個通用的鏈表操作函數可以搞定所有的鏈表,實現了代碼的重用。如果想得到對應結構的指針,可以使用
    發表于 09-25 16:41

    RT-Thread內核中單鏈表的使用與實現

    rt_slist_for_each_entry(node(節點), struct (結構體), list(鏈表所在結構體成員中的名字))3. 單鏈表的實現初始化
    發表于 04-01 12:01

    RT-Thread內核中雙鏈表的使用與實現

    , head)遍歷鏈表中的結構體成員···rt_list_for_each_entry(node(節點), struct (結構體), list(鏈表所在結構體成員中的名字))···安
    發表于 04-01 12:05

    RT-Thread中普通鏈表和侵入式鏈表有何區別

    普通鏈表學習數據結構的時候寫的鏈表是下面這個樣子侵入式鏈表RT-Thread 以及 Linux 內核中鏈表是這樣定義的在使用的時候是這樣
    發表于 04-11 15:15

    rt_timer_check造成任務不執行問題如何處理呢?

    rtthread1和rtthread2的sleep時間同時到達后,會在rt_timer_check,將超時任務由timer移除,放置到ready_
    發表于 05-10 09:47

    淺析RT-Thread中對象容器與雙鏈表的操作

    = rt_hw_interrupt_disable();/* 把對象信息插入到對象鏈表中 */rt_list_insert_after(&(information->object_list
    發表于 05-18 14:23

    小編科普一下rtthread鏈表操作的幾個API與實用的幾個宏

    rtthread 鏈表操作的的幾個 API /* 將節點 n 插入到節點 l 的后面,如果 l 為頭節點,則插入到鏈表頭部 */rt_inline void
    發表于 05-18 14:26

    rt_timer_check 造成任務不執行問題如何解決

    rt_timer_check,將超時任務由timer移除,放置到ready_list中。 由于rtthread1比rtthread2的優先
    發表于 08-09 10:25

    請問一下鏈表這么使用有問題嗎

    ;send_data_cache_head.list)){rt_list_for_each_entry_safe(pos, n, &send_data_cache_head.list,
    發表于 08-29 11:30

    如何去解決單鏈表rt_slist_for_each宏問題呢

    #define rt_slist_for_each(pos, head)for (pos = (head)->next; pos != RT_NULL; pos = pos-&
    發表于 11-10 11:50

    RT-Thread中侵入式鏈表的應用有哪些呢

    上一個結點 /};typedef struct rt_list_node rt_list_t;/ 鏈表類型 */在使用的時候是這樣定義的struct rt_object
    發表于 12-05 13:59

    FreeRTOS代碼剖析之5:鏈表管理list.c

    鏈表是操作系統中常用的數據結構,其結構比較簡單,因此在剖析FreeRTOS的內核時先從這里開始入手。 鏈表是由眾多鏈表節點組成的,在FreeRTOS中,鏈表節點有兩種定義,分別是xLI
    發表于 02-09 02:57 ?694次閱讀
    FreeRTOS代碼剖析之5:<b class='flag-5'>鏈表</b>管理<b class='flag-5'>list</b>.c