RT-Thread 讀後感4 —— 小插曲 rt_list_entry()函式
阿新 • • 發佈:2018-11-11
在學習RT-Thread的時候發現了一個函式rt_list_entry() 改函式的功能是:已知結構體的成員的地址,反推出結構體的首地址的巨集。具體定義如下:
/* 已知一個結構體裡面的成員地址,反推出結構體的首地址 */ #define rt_container_of(ptr,type,member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) #define rt_list_entry(node, type, member) \ rt_container_of(node, type, member)
我們主要關注的是這個地方 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 這裡究竟如何實現的,下面一步步來分析:
先看&((type *)0)->member: 把“0”強制轉換為指標型別,從而該指標指向了資料段的基址,可以取到以“0”為基地址的一個type型變數member域的地址。因此這個地址也就等於member域到結構體基地址的偏移位元組數。
再來看 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))):(char *)(ptr)使得指標的加減操作步長為一位元組,(unsigned long)(&((type*)0)->member)等於ptr指向的member到該member所在結構體基地址的偏移位元組數。二者一減便得出該結構體的地址。轉換為(type *)型的指標,完成!