C 编程/stddef.h/offsetof
外观
C 的 offsetof() 宏是 ANSI C 库中的一个功能,它存在于stddef.h中。它计算给定成员在一个结构体或联合体类型中的偏移量(以字节为单位),表达式类型为size_t。该offsetof() 宏接受两个参数,第一个是结构体名称,第二个是结构体中成员的名称。它不能被描述为 C 原型。[1]
该宏的“传统”实现依赖于编译器对指针的处理并不特别挑剔;它通过指定一个从地址零开始的假设结构体来获取成员的偏移量
#define offsetof(st, m) \
((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
这是通过将空指针强制转换为指向结构体的指针来实现的st,获取结构体中成员m的地址,将该地址强制转换为字符指针,然后使用指针算术来减去结构体的基地址,所有这些都导致结构体开头和成员开头之间的字符位置(即字节)数量。
虽然这在许多编译器中都能正确工作,但根据 C 标准,它具有未定义的行为,因为它涉及空指针的解引用和违反别名规则的强制转换。如果其中一个参数拼写错误,它也会导致令人困惑的编译器诊断。现代编译器通常使用特殊形式定义宏,例如[2]
#define offsetof(st, m) __builtin_offsetof(st, m)
它在 C 中实现通用数据结构时很有用。例如,Linux 内核使用offsetof()来实现container_of(),它允许类似于 Mixin 类型的结构找到包含它的结构体:[3]
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
此宏用于从指向嵌套元素的指针中检索包含结构体,例如此循环遍历my_struct对象的链表
struct my_struct {
const char * name;
struct list_node list;
};
extern struct list_node * list_next(struct list_node *);
struct list_node * iter = /* ... */
while (iter)
{
struct my_struct * elem = container_of(iter, struct my_struct, list);
printf("%s\n", elem->name);
iter = list_next(&elem->list);
}
- ↑ "offsetof reference". MSDN. Retrieved 2010-09-19.
- ↑ "GCC offsetof reference". Free Software Foundation. Retrieved 2010-09-19.
- ↑ Greg Kroah-Hartman (2003-06). "container_of()". Linux Journal. Retrieved 2010-09-19.
{{cite web}}
: Check date values in:|date=
(help)