? ? ? ? C語言的庫函數中提供了計算結構體的一個元素在結構體中的偏移量,以及通過偏移量和結構體中元素的指針計算出來結構體的首地址。但是在一些場景沒有辦法使用C語言庫中的函數,那么就需要自己進行定義。
? ? ? ? 如下面代碼所示的兩個宏定義就完成了計算結構體成員偏移地址,結構體成員首地址的功能。
/*@function: 計算出來“type”結構體類型中,field在結構體中的偏移量*@param type 結構體類型*@param field 結構體成員*@return 偏移量*/
#define offset_of(type, field) ((uint32_t)&(((type *)0)->field)
(1)上面宏中為什么使用“(type *)0”作為指針類型。
? ? ? ? 因為0作為基礎地址,指向類型成員“field”的時候,這時候進行取址,得到的結果就是結構體成員“filed”的結構體內偏移地址。
(2)使用“(type *)0”最為指針,會不會導致內存泄露?
? ? ? ??答案是不會,因為編譯器只關心類型,只要不存在訪問非法地址的內容就不會出現問題,那也是程序運行時的事情,而非編譯時的事情;
????????也就是我們經常說的訪問野指針,空指針,但是上述語句顯然沒有對指針指向的內存進行訪問。
/*@function: 計算出來“ptr”所指向的“type”結構體類型中,指針減去field位置所在的偏移量,從而計算出來結構體的首地址指針*@param ptr 指向結構體成員地址的指針*@param type 結構體類型*@param field 結構體成員*@return 結構體的首地址指針*/
#define container_of(ptr, type, field) ((type *)((uint32_t)ptr - offset_of(type, field)))