这是一个宏,用于计算类中某个成员的地址相对于类实例的偏移量
在C++11中,要求这个类standard_layout
基本用法是这样子的:
#include <stdio.h> /* printf */ #include <stddef.h> /* offsetof */ struct foo { char a; char b[10]; char c; }; int main () { printf ("offsetof(struct foo,a) is %d\n",(int)offsetof(struct foo,a)); printf ("offsetof(struct foo,b) is %d\n",(int)offsetof(struct foo,b)); printf ("offsetof(struct foo,c) is %d\n",(int)offsetof(struct foo,c)); printf("%d\n", &(((struct foo*)0)->c)); return 0; }
注意除了用offsetof宏之外, printf("%d\n", &(((struct foo*)0)->c));也是一种办法
求取某个特定成员的偏移量的意义在哪儿呢?
linux内核中对于这一特性有一个绝佳的应用。内核数据结构中用到了很多的双向链表,进程描述符、页面描述符等等,它们各自被定义成不同
的结构体类型,但就双向链表这一数据结构而言,操作却是完全一致的,听起来该是c++模板大显身手的地方了。
于是就想到定义这样一种链表节点:
struct list_head { struct list_head *next, *prev; };
需要使用双向链表的类型就会含有这样的成员,比如:
typedef struct page { struct list_head list; ..... struct page *next_hash; ..... struct list_head lru; }mem_map_t;
这里面的成员(list或者lru)都会与其它page结构体中对应的链表节点成员相连,相当于成为一个连接件。
问题是我们要的是两个page结构之间相连,你弄成它们的成员相连,怎么用呢??
这就是offsetof大显身手的时候了,有了它,我们在知道成员地址之后,能求出page实例的基地址,从而
变相的实现了将两个page连接在一起的目的,同时复用了双链表这一基本数据结构。
时间: 2024-10-10 09:26:59