Linux Kernel Marco(container_of)

介紹

此 marco 最主要的作用是

你只要傳給他某個 struct 中的 member 的 pointer

他會幫你算出此 struct 的起始位置

也就是說你就可以知道其他 member 的位置並存取

舉例

以下是還沒使用 container_of

先在 main 建立 person 變數,之後使用 print_info 印出 phone_num

如果你目前只能修改 print_info,要如何印出其他 member 的值?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
typedef struct person {
char name[16];
char phone_num[16];
int id;
int year;
}stPerson, *stPerson_ptr;

void print_info(char * phone)
{
printf("Phone num: %s \n",phone);
return;
}

int main(void)
{
stPerson_ptr pJason = malloc( sizeof(stPerson));
strncpy( pJason->name, "Jason", sizeof(pJason->name));
strncpy( pJason->phone_num, "0955123456", sizeof(pJason->phone_num));
pJason->id = 112233;
pJason->year = 28;

print_info(pJason->phone_num);
return 0;
}

使用 container_of

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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) );})


typedef struct person {
char name[16];
char phone_num[16];
int id;
int year;
}stPerson, *stPerson_ptr;

void print_info(char * phone)
{
/* 關鍵是使用 container_of,需要傳入 3 個參數
1. struct 中的某個 member pointer
2. struct 名稱
3. 此 member 在 struct 中的名稱 */
stPerson_ptr pPerson = container_of( phone, stPerson, phone_num );

printf("Name : %s \n",pPerson->name);
printf("Phone num : %s \n",pPerson->phone_num);
printf("ID : %d \n",pPerson->id);
printf("Year : %d \n",pPerson->year);
return;
}

int main(void)
{
stPerson_ptr pJason = malloc( sizeof(stPerson));
strncpy( pJason->name, "Jason", sizeof(pJason->name));
strncpy( pJason->phone_num, "0955123456", sizeof(pJason->phone_num));
pJason->id = 112233;
pJason->year = 28;

print_info(pJason->phone_num);
return 0;
}

參考

非常詳細的介紹