1. 程式人生 > >RT-Thread 讀後感4 —— 小插曲 rt_list_entry()函式

RT-Thread 讀後感4 —— 小插曲 rt_list_entry()函式

在學習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 *)型的指標,完成!