container_of 和 offsetof宏
阿新 • • 發佈:2018-03-01
offsetof container_of 在linux 驅動源碼中,有兩個很有意思的宏,分別是offsetof和container_of,他們的作用和定義是這樣子的
-
offsetof 獲得結構體某成員相對於結構體的偏移長度
/** * 計算的結構體中某成員的偏移量 */ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
這個實現很巧妙,相當於設結構體的整體地址設成0,然後它的成員的地址就相當於成員的偏移
測試代碼:
#include <stdio.h> #include "list.h" typedef struct Test_struct { char ca; int ib; double dc; }Test_struct_t; int main() { printf("offset ca is %d\n",offsetof(Test_struct_t,ca)); printf("offset ib is %d\n",offsetof(Test_struct_t,ib)); printf("offset dc is %d\n",offsetof(Test_struct_t,dc)); return 0; }
執行結果:
offset ca is 0
offset ib is 4
offset dc is 8
2.container_of 是通過結構體的某成員的地址得到整個結構體的地址,在使用上進而可以訪問到結構體的其余成員
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * 通過結構體中的某個成員的指針,反推出來結構體的指針,可以進而可以訪問其他成員 */ #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
實現上實際就是當前這個成員的地址 減去 這個成員相對整個結構體的的偏移量,就是結構體的地址
測試代碼
typedef struct person { char name[20]; char phone_num[12]; int index; }Person_t; void showInfo(Person_t *ptr) { printf("name :%s\n",ptr->name); printf("phone_num :%s\n",ptr->phone_num); printf("index :%d\n",ptr->index); } // 通過姓名打印所以信息 void getInfoByName(char name[]) { if(!name) return ; Person_t *ptr = container_of(name,Person_t,name); if(ptr) { showInfo(ptr); } } int main() { Person_t person; memset(&person,0x0,sizeof(Person_t)); person.index = 110; strncpy(person.name,"zhangsan",strlen("zhangsan")); strncpy(person.phone_num,"15617274954",strlen("15617274954")); showInfo(&person); printf("\============\n"); getInfoByName(&person.name); return 0; }
執行結果
name :zhangsan
phone_num :15617274954
index :110
\============
name :zhangsan
phone_num :15617274954
index :110
container_of 和 offsetof宏