#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
     (type *)( (char *)__mptr - offsetof(type,member) );})
假設有一結構定義如下,且我們只知道phone_num成員的位址,如此便能使用該巨集計算出該結構變數的起始位址:
/* The student structure definition */
typedef struct student {
     char name[16];
     int id;
     char addr[64];
     char phone_num[16];
}STUDENT, *STUDENT_PTR;
該結構記憶體配置圖如下所示:
Figure 1. 結構記憶體配置圖
範例程式碼:
Figure 2. 範例程式碼
以此結構為範例來看containter_of巨集的兩行程式碼:
◎ const typeof( ((type *)0)->member ) *__mptr = (ptr); ==> 得到phone_num的位址 (x+84) ,請參考Figure 1跟Figure 2。
◎ (type *)( (char *)__mptr - offsetof(type,member) ); → (type *)( (char *)__mptr - ((size_t) &((type *)0)->member) ); ==> 其中((size_t) &((type *)0)->member)這段敘述代表以零為起始位址算出member這個成員的相對位址,即為phone_num成員的相對位址,也就是84 (請參考Figure 1)。所以整個敘述變成 (x+84) - 84 = x ,如此便能取得該結構變數的起始位址。
範例程式
3 則留言:
謝謝~~很清楚
感謝您的支持!
gcc會產生warning
in "print_id" function
warning: initialization from incompatible pointer type
張貼留言