Previously in the analysis of the kernel linked list of the article on the CONTAINER_OF macro expansion after the application of the technique.
//offset (struct list, list),-----> expanded ((size_t) & (struct list *) 0, list)//write it clearly when://struct List *p = NULL; &p->list; This is the address of the member list for P, which is the struct pointer, except that p is 0 .//address, starting from the 0 address, calculates the address of the list member, which is the offset of the member list in the struct struct list//The function of this macro is to solve the member member's offset in typeThe reason why the compiler does not error is that the relative offset of the properties of each member in the struct is known at compile time,//access to struct members in code will eventually be converted by the compiler to its relative address//During code run, there is no variable name or attribute member at all, and there are only addresses.
//container_of The final result returns the value of the second expression, where the so-called __mptr is an intermediate pointer variable, which is actually the List_head pointer type, initialized to PTR//And this PTR, as I call it, is the node address in the List_head we're asking for, and defining such an intermediate pointer variable actually takes a lot of factors into account.//If the pass-in is ptr++, there will be side effects, similar to (p++) + (p++)//and (char *) __mptr the reason to cast to Char is essentially because the address is in bytes, and the length of char is a byte//So contain_of is the result of two address subtractionThe //__mptr is the address of the List_head node in the struct, and the offset macro asks for the List_head node's offsets in the struct's type, so//__mptr minus the offset in its structure, which is the address of the struct.
On the code:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define OFFSETOF (TYPE, MEMBER) ((size_t) & ((Type *) 0)->member) #define CONTAINER_OF (PTR, type, MEMBER) ({const typeof (((type *) 0)->member) *__mptr = (pt R);(type *) ((char *) __mptr-offsetof (Type,member));}) struct Cona_t{int i;int j;int v;char t[10];unsigned short xy;}; struct cona_t ct;unsigned short xy;int Main (int Argc,char * argv[]) {int xy;struct cona_t * P;memset (&ct,0,sizeof (struc T cona_t)); ct.i = CT.J = CT.V = 10;sprintf (ct.t, "%s", "SDF"); ct.xy = 20;p = container_of (&ct.xy,struct cona_t,xy);p rint F ("%s\n", p->t); return 0;}
Operation Result:
We can see from the running result that we can get the members of a struct body by a struct pointer.
Application of Linux kernel Container_ofc language