Question: How do I get a pointer to the structure itself from a variable in the structure? /** * 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) ); }) container_of is widely used in the Linux Kernel to obtain the entry address of a member of a structure. For offsetof see stddef.h: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) TYPE Since the base address of the struct is 0, the address of MEMBER is the offset of the MEMBER relative to the address of the struct header. Const typeof(((type *)0->member) *__mptr = (PTR); const typeof((type *)0->member) *__mptr = (PTR); __mptr. (type *)((char *) __mptr-offsetof (type,member)); __mptr (member) = __mptr (member); This pointer is the entry address of member. Case one; The container_of macro is defined in [include/ Linux /kernel.h] : #define container_of(ptr, type, member) / const typeof( ((type *)0)->member ) *__mptr = (ptr); / (type *)( (char *)__mptr – offsetof(type,member) ); The offsetof macro is defined in [include/ Linux /stddef.h] : #define offsetof(type, member) ((size_t) &((type *)0)->member) #include

struct student{


char name[20];  

char sex;

}stu={“zhangsan”,’m’};



main()

{

struct student *stu_ptr; // Store container_of macro return value int offset; // Container_of (&stu.sex,struct student, Const typeof((struct student*)0)->sex) *_mptr = &stu.sex; (struct student *) 0) ->sex); (struct student *) (struct student *) 0) ->sex) Char // (struct student *)0) offset = (int)(&(struct student *)0)->sex); /* (struct student *) * (struct student *) * (struct student *) 0) (struct student *)0)->sex = (struct student *)0)->sex = (struct student *) */ stu_ptr = (struct student *)((char*) _mptr-offset); /* ((char *) _mptr-offset) If _mptr is an integer, _mptr-offset is equivalent to subtracting sizeof (int) * offset bytes. Subtracting offset is equivalent to getting the first address of the structure in which _mptr is located (that is, the address of stu) and then we force that address to be a struct */ printf(“offsetof stu.sex = %d/n”,offset); printf(“stu_ptr->name:%s/tstu_ptr->sex:%c/n”, stu_ptr->name, stu_ptr->sex); return 0; } It is used to get a pointer to a structure variable from a pointer to a domain member variable. Struct demo_struct {struct demo_struct {

2. type1 member1; 3. type2 member2; 4. type3 member3; 5. type4 member4; 6.}; 7. 8. struct demo_struct demo; At the same time, in another place, we get a pointer to a domain member variable in demo, e.g. : 1. Type3 *memp = get_member_POinter_from_SOMEWHERE (); 2. If we need to get Pointers to the entire structure variable, not just one of its domain member variables, we can do this: 1. struct demo_struct *demop = container_of(memp, struct demo_struct, member3); Container_of (memp, struct demo_struct, type3) 1. struct demo_struct *demop = ({ / 2. const typeof( ((struct demo_struct *)0)->member3 ) *__mptr = (memp); / 3. (struct demo_struct *)( (char *)__mptr – offsetof(struct demo_struct, member3) ); }) where typeof is an extension of GNU C to standard C, and its function is to obtain the typeof a variable based on the variable. Therefore, line 2 in the above code first uses Typeof to get the structure domain variable member3 of type Type3, then defines a temporary variable __mptr of type Type3 pointer, and assigns the value of memp, the pointer to the domain variable in the actual structure variable, to the temporary variable __mptr. Assume that the structure variable Demo is located in real memory as shown below: demo +————-+ 0xA000 | member1 | +————-+ 0xA004 | member2 | | | +————-+ 0xA010 | member3 | | | + — — — — — — — — — — — — — + 0 xa018 | member4 | + — — — — — — — — — — — — — +, by performing the line 2 of the above code value is 0 xa010 __mptr. Take a look at line 3 of the code above, where we need to say offsetof, which is defined in include/ Linux /stddef.h as follows: 1. 24#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 1. (struct demo_struct *)( (char *)__mptr – ((size_t) &((struct demo_struct *)0)->member3) ); It can be seen that the implementation principle of offsetof is to take the offset address of the domain member in the structure with respect to address 0, that is, the offsetof the domain member variable with respect to the first address of the structure variable. Therefore, the offsetof(struct demo_struct, member3) call returns the value of member3 relative to the demo variable. Combined with the variable address distribution diagram given above, offsetof(struct demo_struct, member3) will return 0x10. Then, according to the above analysis, at this time, __mptr==0xA010, offsetof(struct demo_struct, member3)==0x10. Therefore, (char *)__mptr – ((size_t) &((struct demo_struct *)0)->member3) == 0xA010-0x10 == 0xA000, which is the starting address of the structure variable demo (as shown above). Thus, container_of implements the ability to get Pointers to the entire structure variable based on a pointer to a domain member variable in a structure variable.