Linux:
      对于定义的一个结构体,有着对应的一套操作函数(eg:遍历、取头节点之类的),如果将对应的结构体指针直接放在结构体内,则操作函数的使用只能被动的限制于该结构体;
   eg:struct page{
                              int a;
                              char bb;
                              struct page *prev, *next;
                           }
  
   int getcount( struct page *head);   该函数将通过head头指针中的next变量来遍历所有结构体,该函数也就只限于page结构体;

---------------------------------------------------------

      将指针提取出来的方式
   eg:struct list_head{
                                   struct list_head *prev, *next;
                                 }                         


         struct page{
                              int a;
                              char bb;
                              struct list_head plist;
                           }

int getcount( struct list_head *head);
            则该函数可以通过head头指针来遍历所有结构体中的list_head成员变量(plist),而通过plist变量地址,可以取得对应的page结构体地址。因此,别的类型的结构体也可以通过内嵌list_head变量来组成链表,而getcout函数就可以用于所有这种类型的结构体操作


首先取出plist在page结构体中的位置偏移:
         #define GETOFFSET(type, member)   (unsigned long)(&((type*)0)->member)
再由plist的地址   -    该偏移值


windows下,在有关IOCP中有用到类似的地方:
      // Calculate the address of the base of the structure given its type, and an
      // address of a field within the structure.
      #define CONTAINING_RECORD(address, type, field) ((type *)( \
                                                  (PCHAR)(address) - \
                                                  (UINT_PTR)(&((type *)0)->field)))

      // Calculate the byte offset of a field in a structure of type type.
      #define FIELD_OFFSET(type, field)    ((LONG)(INT_PTR)&(((type *)0)->field))