container_of
1.1 container_of介紹
定義:container_of在linux內核的include/linux/kernel.h中定義。
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
說明:根據"結構體(type)變量"中的"域成員變量(member)的指針(ptr)"來獲取指向整個結構體變量的指針。
(01) typeof( ( (type *)0)->member ) 取出member成員的變量類型。
(02) const typeof( ((type *)0)->member ) *__mptr = (ptr) 定義變量__mptr指針,並將ptr賦值給__mptr。經過這一步,__mptr爲member數據類型的常量指針,其指向ptr所指向的地址。
(04) (char *)__mptr 將__mptr轉換爲字節型指針。
(05) offsetof(type,member)) 就是獲取"member成員"在"結構體type"中的位置偏移。
(06) (char *)__mptr - offsetof(type,member)) 就是用來獲取"結構體type"的指針的起始地址(爲char *型指針)。
(07) (type *)( (char *)__mptr - offsetof(type,member) ) 就是將"char *類型的結構體type的指針"轉換爲"type *類型的結構體type的指針"。
1.2 container_of示例
代碼(containerof_test.c)
#include <stdio.h>
#include <string.h>
// 獲得結構體(TYPE)的變量成員(MEMBER)在此結構體中的偏移量。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
// 根據"結構體(type)變量"中的"域成員變量(member)的指針(ptr)"來獲取指向整個結構體變量的指針
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct student
{
char gender;
char sex[20];
int age;
char name[20];
};
void main()
{
struct student stu;
struct student *pstu;
stu.gender = '1';
strcpy(stu.sex, "boy");
stu.age = 24;
strcpy(stu.name, "caoft");
// 根據"id地址" 獲取 "結構體的地址"。
pstu = container_of(&stu.sex, struct student, sex);
// 根據獲取到的結構體student的地址,訪問其它成員
printf("gender= %c\n", pstu->gender);
printf("age= %d\n", pstu->age);
printf("name= %s\n", pstu->name);
}
結果:
1.3 container_of圖解
type是結構體,它代表"整體";而member是成員,它是整體中的某一部分,而且member的地址是已知的。
將offsetof看作一個數學問題來看待,問題就相當簡單了:已知'整體'和該整體中'某一個部分',要根據該部分的地址,計算出整體的地址。
巨人的肩膀:
https://www.cnblogs.com/skywang12345/p/3562146.html