温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

container_of 和 offsetof宏

发布时间:2020-07-02 03:20:10 来源:网络 阅读:511 作者:onecan2009 栏目:编程语言

在linux 驱动源码中,有两个很有意思的宏,分别是offsetof和container_of,他们的作用和定义是这样子的

  1. 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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI