【发布时间】:2012-12-12 12:04:11
【问题描述】:
我确实看到定义了一个宏来计算结构偏移量,如下所示
#define offsetof(st, m) ((size_t)(&((st *)0)->m))
但我不明白这个定义是如何工作的。看起来结构的成员是通过NULL 指针访问的。谁能详细说明这个表达式是如何工作的?
【问题讨论】:
-
指针实际上并没有被取消引用。
我确实看到定义了一个宏来计算结构偏移量,如下所示
#define offsetof(st, m) ((size_t)(&((st *)0)->m))
但我不明白这个定义是如何工作的。看起来结构的成员是通过NULL 指针访问的。谁能详细说明这个表达式是如何工作的?
【问题讨论】:
1) 首先创建一个指向“st”类型结构的空指针:(st *)0
2) 接下来取这个结构的成员:->m
3) 接下来获取成员的地址:&(...)
4) 最后将成员的地址转换为 size-t 类型:(size_t)(...)
工作发生在第 3 步,因为指针为空(即地址 == 0),然后成员的地址仅包含结构内的成员位置。
【讨论】:
此表达式在编译时进行了优化,从而在您的程序中产生一个编译时偏移值。
编译器看到一个常量指针 (0),看到一个常量偏移量,然后只应用 constant folding,生成地址 0 + offset(== 偏移量),这正是我们所需要的。
有趣的是,这是否可以在没有任何优化的情况下工作,或者总是进行一些基本的常量折叠。
附:更准确地说,这种优化称为Scalar Replacement of Aggregates,正如下面雷某所指出的那样。
【讨论】: