• offsetof与container_of宏分析


    offsetof宏:结构体成员相对结构体的偏移位置
    container_of:根据结构体成员的地址来获取结构体的地址

    offsetof 宏

    原型:

    #define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)
    

    (TYPE *)0非常巧妙,告诉编译器有一个指向结构体 TYPE 的指针,其地址是0,然后取该指针的 MEMBER 地址 &((TYPE *)0)->MEMBER,因为基址是0,所以这时获取到的 MEMBER 的地址就是相当于在结构体 TYPE 中的偏移量了。
    Example:

    #include <stdlib.h>
    #include <stdio.h>
    #include <stddef.h>
    
    struct TYPE{
        int mem;
        int member;
    };
    
    int main()
    {
        struct TYPE type;
        printf("&type = %p
    ", &type);
        printf("&type.member = %p
    ", &type.member);
        printf("&((struct type *)0)->member = %lu
    ", ((size_t)&((struct TYPE *)0)->member) );
        printf("offsetof(struct TYPE member) = %zd
    ", offsetof(struct TYPE, member));
        return 0;
    }
    /*
    result:
    &type = 0x7ffc1104a110
    &type.member = 0x7ffc1104a114
    &((struct type *)0)->member = 4
    offsetof(struct TYPE member) = 4
    */
    

    container_of 宏

    原型:linux-4.18.5

    /**
     * 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) ({				
    	void *__mptr = (void *)(ptr);					
    	BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&	
    			 !__same_type(*(ptr), void),			
    			 "pointer type mismatch in container_of()");	
    	((type *)(__mptr - offsetof(type, member))); })
    

    网上所见更多是底下这个版本:

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

    第一部分:void *__mptr = (void *)(ptr); const typeof( ((type *)0)->member ) *__mptr = (ptr);
    两个的差别在于 __mptr 的类型一个是 void * ,一个是 type *。
    void * 较为容易理解,下面来看看 type *:
    关于 typeof 关键字其作用是返回变量的类型,简单理解就是如下,详细可参见GCC typeof在kernel中的使用——C语言的“编译时多态”

    int a;
    typeof(a) b; //这等同于int b;
    typeof(&a) c; //这等同于int* c;
    

    因此const typeof( ((type *)0)->member ) *__mptr = (ptr); 的作用就是通过 typeof 获取结构体成员 member 的类型,然后定义一个这个类型的指针变量 __mptr 并将其赋值为 ptr。
    第二部分:(type *)( (char *)__mptr - offsetof(type,member) ),通过offsetof宏计算出 member 在 type 中的偏移,然后用 member 的实际地址__mptr减去偏移,得到 type 的起始地址。从上面关于offsetof宏的 Example 也可以验证这一点:
    &type.member = 0x7ffc1104a114 - &((struct type *)0)->member = 4 = &type = 0x7ffc1104a110

  • 相关阅读:
    浅析深度优先和广度优先遍历实现过程、区别及使用场景
    浅析为什么要用setTimeout模拟setInterval
    app弹出软键盘获取键盘高度不准确的原因及导致底部定位的元素无法贴近键盘的问题
    App平台iOS设备上因内存不足导致白屏、闪退的原因及其解决方案
    浅谈移动端开发技术
    浅析Console命令调试常用方法
    js正则表达式中的正向肯定预查和正向否定预查, 反向肯定和反向否定(这个翻译不准确)
    javascript的版本查看及js的历史
    【转】JS-正则表达式的反向引用
    【转】Linux虚拟网络设备之tun/tap
  • 原文地址:https://www.cnblogs.com/ZhaoxiCheung/p/9610721.html
Copyright © 2020-2023  润新知