先上演示代码
#include <stdio.h> #include <stdlib.h> /* offsetof example */ #include <stddef.h> /* offsetof */ //#define offsetof(type, member) (size_t)&(((type*)0)->member) /** * container_of - 通过结构体的一个成员获取容器结构体的指针 * @ptr: 指向成员的指针。 * @type: 成员所嵌入的容器结构体类型。 * @member: 结构体中的成员名。 * */ #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );}) typedef struct student_info { int id; char name[10]; int age; }student_info; #define DEBUG_COUT(var) do{printf(#var"= %d ",(int)var);}while(0) #define DEBUG_POINT(var) do{printf(#var"= %p ",var);}while(0) int main(void) { printf ("************offsetof example************ "); DEBUG_COUT(offsetof(student_info,id)); DEBUG_COUT(offsetof(student_info,name)); DEBUG_COUT(offsetof(student_info,age)); printf ("************container_of example************ "); student_info *stu = (student_info *)malloc(sizeof(student_info)); stu->age = 18; student_info *ptr = container_of(&(stu->age), student_info, age); DEBUG_POINT(stu);//printf("stu address:%p ", stu); DEBUG_POINT(ptr);//printf("ptr address:%p ", ptr); DEBUG_COUT(ptr->age); system("pause"); return 0; }
make一下并且测试一下
/** * container_of - 通过结构体的一个成员获取容器结构体的指针 * @ptr: 指向成员的指针。 * @type: 成员所嵌入的容器结构体类型。 * @member: 结构体中的成员名。 * */ #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
这个宏的作用其实很简单,就是通过一个容器(结构体)中某个成员的指针得到指向这个容器(结构体)的指针,简单的说就是通过成员找容器。
这个宏的实现代码也就只有两行,下面仔细分析一下:
(1)const typeof( ((type *)0)->member ) *__mptr = (ptr);
定义一个中间变量__mptr,它等于提供给宏的参数ptr,也就是指向某个成员的指针。这个中间变量的命名意义是:
"__"代表内部使用,内核编程中常常这么做;
“m”代表middle。
(2)(type *)( (char *)__mptr - offsetof(type,member) );
这行代码的作用是通过中间变量__mptr(指向某个成员的指针)减去这个成员在容器(结构体)中的偏移来得到指向容器(结构体)的指针。
这里注意偏移的获取offsetof宏的实现