当前位置:编程学习 > C/C++ >>

[C/C++]struct成员的偏移地址的求法

例如
typedef struct struc {
     int a;
     char b[20];
     double ccc;
};
 
现想要求 b 相对于 struc 的偏移地址。

 


其实,很早就知道有 (size_t)&(((struc*)0)->b) 这种写法。昨天,舍友在第三版“面试宝典”上看到这种“怪异”写法,过来问我是怎么回事。

 


我呢,突然产生“用成员地址 - 结构体地址”的想法。试了一下。

 


printf("%d ", ((struc*)&(stc.b) - &stc)); // 居然输出 0 !?

 


但是,分别计算 (struc*)&(stc.b) 和 &stc ,的确相差4字节。// 因为“.”比起地址“&”优先级高,所以 &(stc.b) 就是 &stc.b 。

 


百思不得其解。遂上论坛发问。答曰:“两个指针相减的结果是两指针的偏移量。这个偏移量是相对于指针类型来说的。比如两int型指针相减,得出一个1,不代表二者地址值之差一个字节,这也是不可能的,因为int 类型一般来说是四字节。所以这个1指的是差的了1个 int 的大小(4字节)。同理, ((struc*)&(stc.b) - &stc) , 差的值还不足一个 struc 类型,自然就是 0 了。 如果想看地址差值,则将他们转成数值类型:(intptr_t)&(stc.b) - (intptr_t)&stc 。”  ( 原帖见  http://forum.byr.edu.cn/article/CPP/53484 )

 


恍然大悟!

遂改成

 


printf("%d ", ((stc.b) - (char*)&stc)); // ok!

 

printf("%d ", ((char*)(&stc.b) - (char*)&stc)); // 或许这种写法更准确,如果确保 char 是一个字节的话。

 


又妄想的试了一下

 


printf("%d ", ((bool*)(&stc.b) - (bool*)&stc));

 


发现居然也是正确的 ?!

 


而后,又有高人答曰:“offsetof 一直就是 C 语言标准库的一部分。直接用好了。”

 


标准库?!心里一惊。赶紧翻阅

 


裘宗燕.从问题到程序:程序设计与 C 语言引论.北京:机械工业出版社,2005.9,P372

 


书上曰:“文件<stddef.h> 里包含了标准库的一些常用定义,无论我们包含哪个标准头文件,<stddef.h> 都会被自动包含进来。这个文件里定义:......宏 offsetor ......”

 


offsetor ?! 难道是印刷错误? 我甚至还找到一篇犯同样的错误的博客! 见 html">http://hi.baidu.com/esta_pessoa/blog/item/ffc91b3f225e95e755e72341.html

 


看来就是勘误了,因为我的 VS2008 里没有 offsetor ,只有 offsetof 。还有,<stddef.h> 是要明确包含的,至少我的 VS2008 要求这样。好了,赶紧试一下,

 


printf("%d ", offsetof(stc, stc.b)); // Error!

 


printf("%d ", offsetof(stc, b)); // 还是 Error!!!

 


无语。

 


查 C++ Reference ( http://www.cplusplus.com/reference ),居然要这样

 


printf("%d ", offsetof(struc, b)); // !!!

 

 

虽然还有很多问题不明白,但求偏移地址就到这里吧。

 


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


总结一下,

 


对于一个结构体,例如

 


typedef struct struc {
     int a;
     char b[20];
     double ccc;
};

 


想要求某一成员,例如 b ,相对于 struc 的偏移地址。

 


你可以:

 


// method 1 : 踩着前人的脚步

(size_t)&(((struc*)0)->b)

 


// method 2 : 站在巨人的肩膀上

offsetof(struc, b)  // NOTE :要明确包含 <stddef.h> 头文件

 


// method 3 : 走的人多了却也成了路

(size_t)((char*)(&stc.b) - (char*)&stc)

 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,