首頁 > 軟體

Linux下的兩個經典宏定義

2020-06-16 17:57:36

本文首先介紹Linux下的經典宏定義,感受極客的智慧,然後根據該經典定義為下篇文章作鋪墊。

offsetof宏定義:

// 獲得結構體(TYPE)的變數成員(MEMBER)在此結構體中的偏移量。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

說明:獲得結構體(TYPE)的變數成員(MEMBER)在此結構體中的偏移量。
1.( (TYPE *)0 ) 將零轉型為TYPE型別指標,即TYPE型別的指標的地址是0。
2.((TYPE *)0)->MEMBER    存取結構中的資料成員。
3.&( ( (TYPE *)0 )->MEMBER )  取出資料成員的地址。由於TYPE的地址是0,這裡獲取到的地址就是相對MEMBER在TYPE中的偏移。
4.(size_t)(&(((TYPE*)0)->MEMBER))  結果轉換型別。對於32位元系統而言,size_t是unsigned int型別;對於64位元系統而言,size_t是unsigned long型別。

使用範例:

struct student
{
 char gender;
 int id;
 int age;
 char name[20];
};


int _tmain(int argc, _TCHAR* argv[])
{
 int gender_offset, id_offset, age_offset, name_offset;


 gender_offset = offsetof(struct student, gender);
 id_offset = offsetof(struct student, id);
 age_offset = offsetof(struct student, age);
 name_offset = offsetof(struct student, name);


 printf("gender_offset = %dn", gender_offset);
 printf("id_offset = %dn", id_offset);
 printf("age_offset = %dn", age_offset);
 printf("name_offset = %dn", name_offset);


 system("pause");
 return 0;
}
//結果:
/*
gender_offset = 0
id_offset = 4 //位元組對其
age_offset = 8
name_offset = 12
*/

offsetof圖解

TYPE是結構體,它代表"整體";而MEMBER是成員,它是整體中的某一部分。

container_of宏定義:

#define container_of(ptr, type, member) ({         
    const typeof( ((type *)0)->member ) *__mptr = (ptr);   
    (type *)( (char *)__mptr - offsetof(type,member) );})

說明:根據"結構體(type)變數"中的"域成員變數(member)的指標(ptr)"來獲取指向整個結構體變數的指標。
1. typeof( ( (type *)0)->member )    取出member成員的變數型別。
2.const typeof( ((type *)0)->member ) *__mptr = (ptr)    定義變數__mptr指標,並將ptr賦值給__mptr。經過這一步,__mptr為member資料型別的常數指標,其指向ptr所指向的地址。
3. (char *)__mptr    將__mptr轉換為位元組型指標。
4. offsetof(type,member))    就是獲取"member成員"在"結構體type"中的位置偏移。
5. (char *)__mptr - offsetof(type,member))    就是用來獲取"結構體type"的指標的起始地址(為char *型指標)。
6.(type *)( (char *)__mptr - offsetof(type,member) )    就是將"char *型別的結構體type的指標"轉換為"type *型別的結構體type的指標"。
7.反斜槓“/”表示行連線

更多詳情見請繼續閱讀下一頁的精彩內容http://www.linuxidc.com/Linux/2015-07/120014p2.htm


IT145.com E-mail:sddin#qq.com