Linux / offsetof 和 container_of
1、?offsetof?
(1)原型
/** @member TYPE : 結構體原型。* MEMBER : 結構體成員。 */ #define offsetof(TYPE , MEMBER) ((size_t) &((TYPE *)0)->MEMBER)?
(2)文件路徑:/ include / linux / stddef.h
(3)作用
返回指定類型(TYPE)的成員(MEMBER)在該結構體內的偏移量。
(4)解析
? ? ? ? ?A、(TYPE *) 0
? ? ? ? ? ? ? ? ? 將以地址 0 為開始的,大小為 sizeof(TYPE) 的內存塊按照 TYPE 進行看待。注意,這里只是看待,并沒有進行讀? ? ? ? ? ? ? ? 取!這就保證了代碼執行到這里并不會報錯!
? ? ? ? ?B、((TYPE *) 0) -> MEMBER
? ? ? ? ? ? ? ? ? 看看 MEMBER 成員,還是沒有讀取。
? ? ? ? ?C、&(((TYPE *) 0) -> MEMBER)
? ? ? ? ? ? ? ? ?看看 MEMBER 成員地址,還是沒有讀取。因為結構體的首地址為0,所以得到的 MEMBER 的首地址就是該成員相對? ? ? ? ? ? 于結構體首地址的偏移量。
? ? ? ? ?D、(size_t)&(((TYPE *)0) -> MEMBER)
? ? ? ? ? ? ? ? ?將該地址轉為 size_t 類型。
? ? ? ? ? 在32位系統中,size_t 的原型是 unsigned int 。
? ? ? ? ? 在64位系統中,size_t 的原型是 unsigned long 。
(5)栗子
#include <iostream>#define offsetof_t(TYPE , MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))struct stest {char c;int i;float f;double d; };int main() {int pos_c = offsetof_t(stest , c);int pos_i = offsetof_t(stest , i);int pos_f = offsetof_t(stest , f);int pos_d = offsetof_t(stest , d);std::cout << "stest::c 的偏移量:" << pos_c << std::endl;std::cout << "stest::i 的偏移量:" << pos_i << std::endl;std::cout << "stest::f 的偏移量:" << pos_f << std::endl;std::cout << "stest::d 的偏移量:" << pos_d << std::endl;return 0; }結果:
stest::c 的偏移量:0 stest::i 的偏移量:4 stest::f 的偏移量:8 stest::d 的偏移量:16?
2、container_of
(1)原型
/** @member ptr 結構體成員的地址。* type 結構體原型。* member 結構體成員。*/ #define container_of(ptr, type, member) ({ \const typeof( ((type *)0)->member ) *__mptr = (ptr); \(type *)( (char *)__mptr - offsetof(type,member) );})(2)文件路徑:/ include / linux / kernel.h
(3)作用:通過結構體成員地址反推該結構體的地址。
(4)解析
? ? ? ? ?A、typeof(? ( (type*)0 ) -> member ) )
? ? ? ? ? ? ? ? ? 獲得 member 成員的數據類型。
? ? ? ? ?B、const?typeof(? ( (type*)0 ) -> member ) )? *_mptr = (ptr)
? ? ? ? ? ? ? ? ? 定義常量指針?_mptr,指向 ptr 指向的內容,該指針變量指向的內容是不可變的。
? ? ? ? ?C、(char *)_mptr - offsetof(type , member)
? ? ? ? ? ? ? ? ? 前者將 _mptr 變為 字符指針,后者返回 member 在 type 的偏移量,二者相減就是 type 的首地址了。
? ? ? ? ? ?最后在通過? (type *) 轉為 type 型地址就可以了。
(5)栗子
#include <iostream>struct stest {char c;int i;float f;double d; };#define offsetof_t(TYPE , MEMBER) ((size_t)&(((TYPE *)0)->MEMBER))#define container_of_test(ptr , type , member) ({\const typeof(((type *)0)->member) *_mptr = ptr;\(type *)((char *)ptr - offsetof_t(type , member));})int main() {stest test1;stest *p;p = container_of_test(&test1.i , stest , i);if (p == &test1){std::cout << "二者相同。" << std::endl;}else{std::cout << "二者不同。" << std::endl;} }結果:
二者相同?
?
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的Linux / offsetof 和 container_of的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批处理命令 / 延迟环境变量扩展
- 下一篇: linux 其他常用命令