认真理解 offsetof宏定义

我们经常遇到一种场景,比如把 链表结点或者队列结点 放入到 数据结构体 中,当我们知道结点地址,想要得到数据结构的地址,下面这个宏可以出场了。

#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER ) 

举例: 

#include<stdio.h> 
typedef struct _test 
{ 
  char i; 
  int j; 
  char k; 
}Test; 
int main() 
{ 
  Test *p = 0; 
  printf("%p ", &(p->k)); 
} 

 

大概可以总结为以下4步: 

1. ( (TYPE *)0 ) 将零转型为TYPE类型指针; 
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员; 
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址; 
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型.巧妙之处在于将0转换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址; 

结果很好,但是自己有两个疑问:

1.结构体中,成员变量表示的地址在内存中是怎样分布得,会以什么结果显示?

2.强转0指针,上面只做第二步操作会不会挂掉?

 

举例:

struct item_s{

  void *data;

  struct item_s *next;

};

int main(int argc,char **argv){

  struct item_s item_ins={0};

  struct item_s *itemp_ins=NULL;

  1.printf(&item_ins);

  2.printf(&(item_ins.is_tmp));

  3.printf(itemp_ins->is_tmp);

  4.printf("%x\n",&(itemp_ins->is_tmp))

}

 

然后疑问解决,通过1 2结果对比,会发现,他们的差值即为 成员地址相对结构体地址 的偏移量。通过3 4结果对比,会发现,在一个地址为0x0上是不能直接做取操作得,但是通过取地址符操作可以取得偏移量。

posted @ 2014-04-15 10:34  克莱尔孙  阅读(495)  评论(0编辑  收藏  举报