(type *)( (char *)__mptr - offsetof(type,member) );})
不妨再来看看offset_of宏:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
// 将地址0强制解析为Type型指针,并访问其Member成员。然后用&取member的地址,这个地址-0就是
// member与type型变量的首地址的偏移量。因为起始点为0,因此直接取地址就ok了
由以上两个宏的实现可以看出,在涉及结构体和其成员的偏移计算中,经常使用的技巧是将0地址强制转换成结构体指针,然后访问该结构体的成员。其实这源于一个很简单的事实,下面a,b,c三个值是相等的:
a:结构体类型定义中,其某个成员的首地址和结构体类型的首地址的差值
b:结构体变量中,其某个成员变量的首地址和该结构体变量的首地址的差值
c:结构体变量中成员变量的指针,和结构体变量的指针的差值
以上事实是由结构体的特性(编译器对结构体处理的约定、结构体在内存中存储的约定等)保证的。