zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    HDU 1075 What Are You Talking About(字典树)
    HDU 1075 What Are You Talking About (stl之map映射)
    HDU 1247 Hat’s Words(字典树活用)
    字典树HihoCoder
    HDU 1277全文检索(字典树)
    HDU 3294 Girls' research(manachar模板题)
    HDU 3294 Girls' research(manachar模板题)
    HDU 4763 Theme Section(KMP灵活应用)
    Ordering Tasks UVA
    Abbott's Revenge UVA
  • 原文地址:https://www.cnblogs.com/ZhaoxiCheung/p/9610721.html
Copyright © 2011-2022 走看看