struct 中的member variable 的offset的宏定义

来源:互联网 发布:标题优化软件设计 编辑:程序博客网 时间:2024/06/04 17:41

 

struct 中的member variable 的offset的宏定义

#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))

定义:#define offsetof(type, f) ((size_t) ((char *)&((type *)0)->f - (char *)(type *)0))

解释:

【akirya】:
先将0转化为 type*类型的指针,然后取得成员变量的地址,在减去0
最后得到的就是 成员变量的偏移地址.
【Jarrylogin】:
0转化为 type*类型的指针是不是空指针?它如何知道f
【qwe896】:
http://c-faq-chn.sourceforge.net/ccfaq/node30.html
我在上面网页中找到的这个解释,你看是不是正确:
3.12 如何确定域在结构中的字节偏移?
ANSI C在<stddef.h> 中定义了offsetof() 宏, 用 offsetof(struct s, f) 可以计算出域 f 在结构 s 中的偏移量。 如果出于某种原因, 你需要自己实现这个功能, 可以使用下边这样的代码:
#define offsetof(type, f) ((size_t)
    ((char *)&((type *)0)->f - (char *)(type *)0))
这种实现不是 100% 的可移植; 某些编译器可能会合法地拒绝接受。
【akirya】:
你知道结构体怎么找到成员变量的么?
就是结构体对象的地址+偏移量;
struct type
{
int x;
int f;
};
type*p = new type;
printf("%d,%d/n",p,&(p->f));
这样的输出你能理解么
只不过那个宏 现将0转化为type*类型
只要不访问成员变量就不会引起访问违规.
to  qwe896(老蒋)
能不能列举一个 无法编译这样代码的C编译器?
【Chiyer】:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
然后到网上查了一下,发现还真的是很有用,附带一位大侠的解说:
  struct   AAA  
  {  
  int   i;  
  int   j;  
  };  
  struct AAA *pAAA;  
  pAAA=new AAA;  
  这时,pAAA实际上是一个Pointer, 指向某一确定的内存地址,比如0x1234;  
  而 pAAA->i 整体是一个int型变量,其地址是&(pAAA->i) ,'&'为取址运算符;  
  那么&(pAAA->i)一定等于0x1234,因为i是结构体AAA的第一个元素。  
  而&(pAAA->j)一定是0x1234 + 0x4 = 0x1238; 因为sizeof(int) = 4;
  这个做法的巧妙之处就是:它把“0”作为上例中的pAAA,那么 &(pAAA->j)就是j的  
  offset啦
  解析结果是:  
  (s   *)0 ,将 0 强制转换为Pointer to   "s"    
  可以记 pS = (s *)0 ,pS是指向s的指针,它的值是0;  
  那么pS->m就是m这个元素了,而&(pS->m)就是m的地址,而在本例中就是offset啦  
  再把结果强制转换为size_t型的就OK 了,size_t其实也就是int啦!!
【ky310】:
支持一下
【yulefox】:
#define offsetof(type, f) ((size_t) /
((char *)&((type *)0)->f - (char *)(type *)0))
type为class或struct类型名,f为type类型成员。现在要确定f在type对象模型中的空间位置,很自然地想到将一个type类型对象起始地址设为0,再计算出f的起始地址,二者之差即为f在type中的位置:
type类型对象:(type *)0
对象起始地址:(char *)&((type *)0),char *是为了保证字节为单位,只要你不试图去改变它,这样是合法的
f的起始地址:((char *)&((type *)0)->f
【Jarrylogin】:
越来越混了
(s   *)0 ,将 0 强制转换为Pointer to   "s"    
  可以记 pS = (s *)0 ,pS是指向s的指针,它的值是0;  
pS->m就是m这个元素?0明显不等于0x1234,那如何找到m,是不是我理解错误?
【Jarrylogin】:
只要不访问成员变量就不会引起访问违规.怎么理解?
【akirya】:
int *p=0;
*p=1;访问违规
pS->m就是m这个元素?0明显不等于0x1234,那如何找到m,是不是我理解错误?
在这个时候编译器会将计算this+偏移地址
pS->m=0;会对this+偏移地址的内容进行赋值
【Jarrylogin】:
你是说 0在此处时编译器会将它看成this指针?
【akirya】:
说习惯了this是指结构体变量的地址.
不是看成
代码中 (type *)0 就是强制转换
&((type *)0)->f
这个是一部分
(char *)&((type *)0)->f
这个也是一部分
(char *)(type *)0)
分开看就容易理解了
【contain_universe】:
#define offsetof(type, f) ((size_t)((char *)&((type *)0)->f - (char *)(type *)0))
宏定义是:求得成员f在type变量中的偏移量
给你个调用实例
struct list{
  char ch;
  int  num;
  int  f;
}demo;
size_t offset = offsetof(demo, f);
上面说的也不错
【Jarrylogin】:
请问楼上此处0和this指针是如何联系上的?
【akirya】:
this指针是在struct内部使用的
外部用的话就是结构体的指针了,通常两个值是一样的
【Jarrylogin】:
我是问(type *)0和this指针是如何联系上的?我可能没有表述清楚
【akirya】:
struct type
{
int x;
int f;
};
type* p=(type *)0;
printf("%d",&(p->f));
这样能理解了么?

 

另一解:

#define   OFFSET(structure,   member)     ((int)   &((structure   *)0)->member)  
  0这里指的是指针0处,这样结构的第一个成员就与0对齐了,取member的地址当然就是偏移了。当然,该偏移不能直接用,需要强制转换为int。

原创粉丝点击