container_of(ptr, type, member)宏定义解析
生活随笔
收集整理的這篇文章主要介紹了
container_of(ptr, type, member)宏定义解析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
container_of()這個宏定義的功能是根據一個已知結構體成員的指針和變量名得出宿主結構體的地址
為方便理解和描述,本文中將已知的結構體成員叫做功能成員,它所在的結構體叫做宿主結構體。
先來分析一下參數: ptr:指向功能成員的指針,存放功能成員的地址 type:宿主結構體的類型 member:功能成員在結構體中的表示(變量名)
container_of(ptr, type, member)的完整宏展開: container_of(ptr, type, member) ({ const typeof( ((type*)0)->member ) *__mptr = (ptr) ; (type*)( (char *)__mptr - offsetof(type, member) ) ; })
第2行,可能大伙看得有點蒙,先來分解一下這個語句的結構 我們定義一個變量的格式是:修飾符+變量類型+變量名 = 右值; 修飾符 ? ? ? ? ? ?變量類型 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?變量名 ? ? 右值 const ? ? typeof( ((type*)0)->member ) ? ?*__mptr = ?(ptr) ;
現在看明白了嗎,拋開具體細節,“typeof( ((type*)0)->member )”代表的是一種數據類型,那么它是什么樣的數據類型呢? ((type*)0):它把0轉換為一個type類型(也就是宿主結構體類型),為什么要這樣做,且看后文
((type*)0)->member:這個0指針指向結構體中的member成員
typeof是gcc的c語言擴展保留字,用于獲取變量的類型 ?typeof( ((type*)0)->member ) ? ?*:得出member的數據類型
所以,第2行的結果就是定義一個指向member的指針,并賦值為ptr
第3行,我們先看后半部分?offsetof(type, member); offsetof定義在/include/linux/stddef.h中 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 根據前面的講解可以知道:&((TYPE *)0)->MEMBER獲得MEMBER的地址,再轉為size_t類型作為一個整數,由于此時&stu=0,因為結構體的基地址為0,所以MEMBER自然為其在結構體中的偏移地址。當然也可以把0換成1,這時&stu=1,要想得出功能成員相對于宿主結構體的偏移量還得在后面減去1,所以用0的好處就是使得功能成員的地址是相對于宿主結構體的偏移量。回到第2行,將0改為其他的任意正整數如“1”,并不影響最后的結果,因為在第二行中的目的僅僅是獲得member的數據類型而已。
(char *)__mptr - offsetof(type, member):用第2行獲得的結構體成員地址減去其在結構體中的偏移值便可得到宿主結構體的地址 可能有些同學覺得疑問,為什么要把__mptr轉換為char類型的指針呢,C語言中,一個指向特定數據類型的指針減1,實際上減去的是它所指向數據類型的字節大小sizeof(data),所以這里要把它轉換成char類型,不然得不出正確結果 (type*)( (char *)__mptr - offsetof(type, member) )?最后把地址轉換成宿主結構體的類型type
由此,container_of()實現了根據一個已知結構體成員的指針和變量名得出宿主結構體的地址的功能
轉載:http://blog.csdn.net/u010415192/article/details/49523143
先來分析一下參數: ptr:指向功能成員的指針,存放功能成員的地址 type:宿主結構體的類型 member:功能成員在結構體中的表示(變量名)
container_of(ptr, type, member)的完整宏展開: container_of(ptr, type, member) ({ const typeof( ((type*)0)->member ) *__mptr = (ptr) ; (type*)( (char *)__mptr - offsetof(type, member) ) ; })
第2行,可能大伙看得有點蒙,先來分解一下這個語句的結構 我們定義一個變量的格式是:修飾符+變量類型+變量名 = 右值; 修飾符 ? ? ? ? ? ?變量類型 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?變量名 ? ? 右值 const ? ? typeof( ((type*)0)->member ) ? ?*__mptr = ?(ptr) ;
現在看明白了嗎,拋開具體細節,“typeof( ((type*)0)->member )”代表的是一種數據類型,那么它是什么樣的數據類型呢? ((type*)0):它把0轉換為一個type類型(也就是宿主結構體類型),為什么要這樣做,且看后文
((type*)0)->member:這個0指針指向結構體中的member成員
typeof是gcc的c語言擴展保留字,用于獲取變量的類型 ?typeof( ((type*)0)->member ) ? ?*:得出member的數據類型
所以,第2行的結果就是定義一個指向member的指針,并賦值為ptr
第3行,我們先看后半部分?offsetof(type, member); offsetof定義在/include/linux/stddef.h中 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 根據前面的講解可以知道:&((TYPE *)0)->MEMBER獲得MEMBER的地址,再轉為size_t類型作為一個整數,由于此時&stu=0,因為結構體的基地址為0,所以MEMBER自然為其在結構體中的偏移地址。當然也可以把0換成1,這時&stu=1,要想得出功能成員相對于宿主結構體的偏移量還得在后面減去1,所以用0的好處就是使得功能成員的地址是相對于宿主結構體的偏移量。回到第2行,將0改為其他的任意正整數如“1”,并不影響最后的結果,因為在第二行中的目的僅僅是獲得member的數據類型而已。
(char *)__mptr - offsetof(type, member):用第2行獲得的結構體成員地址減去其在結構體中的偏移值便可得到宿主結構體的地址 可能有些同學覺得疑問,為什么要把__mptr轉換為char類型的指針呢,C語言中,一個指向特定數據類型的指針減1,實際上減去的是它所指向數據類型的字節大小sizeof(data),所以這里要把它轉換成char類型,不然得不出正確結果 (type*)( (char *)__mptr - offsetof(type, member) )?最后把地址轉換成宿主結構體的類型type
由此,container_of()實現了根據一個已知結構體成員的指針和變量名得出宿主結構體的地址的功能
轉載:http://blog.csdn.net/u010415192/article/details/49523143
總結
以上是生活随笔為你收集整理的container_of(ptr, type, member)宏定义解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Linux中设置UMASK值
- 下一篇: 把DXF导入到Altium Design