offsetof与container_of概述

offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址来获取结构体的地址

使用offsetof宏需要包含stddef.h头文件
#define offsetof(type, member) (size_t)&(((type*)0)->member)巧妙之处在于将地址0强制转换为type类型的指针,从而定位到member在结构体中偏移位置。编译器认为0是一个有效的地址,从而认为0是type指针的起始地址。

使用container_of宏需要包含linux/kernel.h头文件

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

 ptr:表示结构体中member的地址
 type:表示结构体类型
 member:表示结构体中的成员
通过ptr的地址可以返回结构体的首地址

container_of宏分为两部分,

第一部分:const typeof( ((type *)0)->member ) *__mptr = (ptr);

通过typeof定义一个member指针类型的指针变量__mptr,(即__mptr是指向member类型的指针),并将__mptr赋值为ptr。

第二部分: (type *)( (char *)__mptr - offsetof(type,member) ),通过offsetof宏计算出member在type中的偏移,然后用member的实际地址__mptr减去偏移,得到type的起始地址,即指向type类型的指针。

第一部分的目的是为了将统一转换为member类型指针。

#include <stdio.h>
#include <stdlib.h>

#define NAME_STR_LEN  32
#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 student_info
{
    int  id;
    char name[NAME_STR_LEN];
    int  age;
}student_info;

int main()
{
    size_t off_set = 0;
    off_set = offsetof(student_info, id);
    printf("id offset: %u\n",off_set);
    off_set = offsetof(student_info, name);
    printf("name offset: %u\n",off_set);
    off_set = offsetof(student_info, age);
    printf("age offset: %u\n",off_set);
    student_info *stu = (student_info *)malloc(sizeof(student_info));
    stu->age = 10;
    student_info *ptr = container_of(&(stu->age), student_info, age);
    printf("age:%d\n", ptr->age);
    printf("stu address:%p\n", stu);
    printf("ptr address:%p\n", ptr);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wteruiycbqqvwt/article/details/112260967