一、在linux kernel中關於offsetof與container_of巨集的定義為:
二、offsetof巨集介紹
b. offsetof巨集的原理:我們虛擬乙個type型別結構體變數,然後用type.member的方式來訪問那個member元素,繼而得到
member相對於整個變數首位址的偏移量。
c. 學習思路:
第一步:先學會用offsetof巨集
第二步:再去理解這個巨集的實現原理
(type *)0,這是乙個強制型別轉換,把0位址強制型別轉換成乙個指標,這個指標指向乙個type型別的結構體變數。
(實際上這個結構體變數可能不存在,但是只要我們不要解引用這個指標就不會出錯)。
((type *)0)->member,(type *)0是乙個type型別結構體變數的指標,通過指標來訪問這個結構體變數的member元素。
&((type *)0)->member 等效於&(((type *)0)->member),意義就是得到member元素的位址,但是因為整個結構體變數的首 位址為0。
三、container_of巨集介紹
a. 作用:知道乙個結構體中某個元素的指標,反推這個結構體變數的指標,有了container_of巨集,我們可以從乙個元素的指標得到整個結構體變數的指標,繼而得到結構體中其他元素的指標。
b.typeof關鍵字的作用是:typeof(a)時由變數a得到a的型別,typeof就是由變數名得到變數資料型別的。
c.這個巨集的工作原理:先用typeof得到member元素的型別定義成乙個指標,然後用這個指標減去改元素相對於整個結構體變數的偏移量(偏移量用offsetof巨集得到的),減去之後得到的就是整個結構體變數的首位址了,再把這個這個位址強制型別轉換為type *即可。
四、應用舉例
在原始檔: leds-s5pv210-platform.c中有用到為例,進行分析
解析: 由於在s5pv210_led_set(...)函式中傳參是struct
led_classdev
*led_cdev
,而在struct
led_classdev結構體中不存在gpio編號,而沒法直接操作硬體,故技巧性的定義了結構體s5pv210_gpio_led
,在這個結構體裡面包含了struct
led_classdev
cdev元素,所以在知道元素cdev的位址時就可以知道結構體s5pv210_gpio_led的基位址,從而可以獲得pdata的位址,
struct
s5pv210_led_platdata 包含了成員gpio
,故可以獲取到對應的gpio值,順利操作硬體。
container of與offsetof的原理
container of是linux核心中使用非常頻繁的乙個巨集,用於從包含在某個結構中的指標獲得結構本身的指標,通俗地講就是通過結構體變數中某個成員的首位址進而獲得整個結構體變數的首位址。define container of ptr,type,member 其中offsetof的定義 defin...
offsetof與container of巨集解析
1 前言 今天在看 時,遇到offsetof和container of兩個巨集,覺得很有意思,功能很強大。offsetof是用來判斷結構體中成員的偏移位置,container of巨集用來根據成員的位址來獲取結構體的位址。兩個巨集設計的很巧妙,值得學習。linux核心中有著兩個巨集的定義,並在鍊錶結...
關於offsetof巨集
offsetof 巨集 這是在看書的時候遇到的,估計以後會用到,避免遺忘,先記下來吧。一般形式 define offsetof type,member size t type 0 member 說明 通過 type 0 將0位址強制轉換為type結構型別中的指標 通過 type 0 member 訪...