天天看點

C語言之offsetof宏和container_of宏

  首先我們要明白一點通過結構體變量來通路結構體中的各個元素時,其本質上是

通過指針的方式來實作通路的,隻不過是這個時候編譯器幫自動幫我們計算了每個

元素與結構體起始位址之間的偏移量而已

一:offsetof宏:

<code>#define offsetof(TYPE, MEMBER) ((int) &amp;((TYPE *)0)-&gt;MEMBER)</code>

1:參數與傳回值分析:

 (1)TYPE是結構體類型,MEMBER是結構體中一個元素的元素名

  (2)這個宏傳回的是member元素相對于整個結構體變量的首位址的偏移量,類型是int

2:作用于原理

  (1)offsetof宏的作用是:用宏來計算結構體中某個元素和結構體首位址的偏移

量(其實質是通過編譯器來幫我們計算)。

  (2)offsetof宏的原理:我們虛拟一個type類型結構體變量,然後用type.member

的方式來通路那個member元素,繼而得到member相對于整個變量首位址的偏移量。

3:從結合方式方面來分析:

(TYPE *)0 這是一個強制類型轉換,把0位址強制類型轉換成一個指針,這個指針指

向一個TYPE類型的結構體變量。 (實際上這個結構體變量可能不存在,但是隻要我

不去解引用這個指針就不會出錯)。

((TYPE *)0)-&gt;MEMBER (TYPE *)0是一個TYPE類型結構體變量的指針,通過指針指針

來通路這個結構體變量的member元素

&amp;((TYPE *)0)-&gt;MEMBER  等效于&amp;(((TYPE *)0)-&gt;MEMBER),意義就是得到member元

素的位址。但是因為整個結構體變量的首位址是0,是以得到的member元素的位址就

是member元素的偏移量。

二:container_of宏

<code>#define container_of(ptr, type, member) ({\</code>

<code>const</code> <code>typeof(((type *)0)-&gt;member) * __mptr = (ptr);\</code>

<code>(type *)((</code><code>char</code> <code>*)__mptr - offsetof(type, member)); }</code>

<code>注意:這裡的 \ 是連行符</code>

 (1)ptr是指向結構體元素member的指針,type是結構體類型,member是結構體

中一個元素的元素名

 (2)這個宏傳回的就是指向整個結構體變量的指針,類型是(type *)

2:作用與原理分析:

  (1)作用:知道一個結構體中某個元素的指針,反推這個結構體變量的指針。有 

了container_of宏,我們可以從一個元素的指針得到整個結構體變量的指針,繼而

得到結構體中其他元素的指針。

  (2)typeof關鍵字的作用是:typepof(a)時由變量a得到a的類型,typeof就是由 

變量名得到變量資料類型的。

  (3)這個宏的工作原理:先用typeof得到member元素的類型定義成一個指針,然

後用這個指針減去該元素相對于整個結構體變量的偏移量(偏移量用offsetof宏得

到的),減去之後得到的就是整個結構體變量的首位址了,再把這個位址強制類型

轉換為type *即可。

本文轉自 菜鳥養成記 51CTO部落格,原文連結:http://blog.51cto.com/11674570/1862701

繼續閱讀