1. OFFSETOF macro
#define offsetof (Type, MEMBER) ((size_t) & ((TYPE *) 0)->member)
Cast address 0 to a pointer of type types, resulting in an offset of the struct member member relative to the start address of the struct.
2. CONTAINER_OF macro
#define container_of (PTR, type, member) ({ consttypeof((type *)0) Member) *__mptr = (PTR); *) ((char *) __mptr-offsetof (Type,member));})
Effect: the member member address of the struct (type) minus the offset of member in the type gets the starting address of the struct (type).
The CONTAINER_OF macro is divided into two parts:
First part: Const typeof (((type *) 0)->member) *__mptr = (PTR);
Define a pointer variable __mptr of member pointer type by typeof and assign __mptr to PTR.
Part II: (Type *) ((char *) __mptr-offsetof (type,member));
The Offsetof macro calculates the offset of the member in the type,
Then subtract the offset with the actual address of the member __mptr, and get the start address of the type, which is a pointer to type.
Test code:
1#include <stdio.h>2 3 #defineOffsetof (Type, MEMBER) ((size_t) & ((type *) 0)->member)4 5 #defineContainer_of (PTR, type, member) ({6 Const typeof((Type *)0)->member) *__mptr =(PTR); 7(Type *) ( (Char*) __mptr-Offsetof (type, member));})8 9typedefstruct{Ten intID; One Charname[ -]; A intAge ; - }student; - the intMain () - { -printf"%lu\n", Offsetof (student, id)); -printf"%lu\n", Offsetof (student, name)); +printf"%lu\n", Offsetof (student, age)); - + student S; AS.age = -; atStudent *ps = container_of (&S.age, student, age); -printf"%d\n", ps->Age ); -printf"%p\n", &s); -printf"%p\n", PS); - - return 0; in}
Operation Result:
Summary of CONTAINER_OF macros and OFFSETOF macros