【发布时间】:2015-08-28 02:11:08
【问题描述】:
我试图理解 c 中的偏移宏,但在尝试解释时遇到了问题
&((type *)0) 在
#define offsetof(type, member) ((size_t) &((type *)0)->member)
我如何阅读它。我了解其功能,但不了解该术语的确切解释。
谢谢
【问题讨论】:
我试图理解 c 中的偏移宏,但在尝试解释时遇到了问题
&((type *)0) 在
#define offsetof(type, member) ((size_t) &((type *)0)->member)
我如何阅读它。我了解其功能,但不了解该术语的确切解释。
谢谢
【问题讨论】:
这个预处理器宏的扩展:
#define offsetof(type, member) ((size_t) &((type *)0)->member)
导致以下正式定义:给定type 上的offsetof 是给定type 的member 成员地址的size_t 的转换。在空指针地址。
或者,换句话说,这是获取member的地址的黑魔法,就好像type的对象存在于空指针地址(注意:只要这里没有发生读取或写入,就不会崩溃)。由于此类成员的地址现在是绝对的(相对于零),因此可以将其值安全地转换为 size_t,从而有效地将此类 member 的偏移量计算为绝对值。
希望这会有所帮助!
【讨论】:
0 不同,您就会遇到麻烦。沙丁鱼确实很好地做到了这一点。所以,我不会称其为“黑魔法”,而是“肮脏(但通常有效)的黑客”。已被 C11 取代。
offsetof 无论如何都是/是实现定义的,因此假设在 OP 正在调查的平台中,空指针的值确实为零。
看看这段代码:
type *x = 0;
size_t y = &x->member;
通常,y 将等于 x+offset,但因为 x=0,我们只能得到偏移量。
在代码中我们写((type *)0)——直接返回指向type类型0的指针,而不创建x变量,然后我们获取成员((type *)0)->member)的地址。所有这些都被定义为size_t 变量。
【讨论】: