使用offsetof编写链结构

来源:互联网 发布:python zork 编辑:程序博客网 时间:2024/05/29 15:45

在c中,要实现一个通用的双向链表,我们一般的做法是这样定义节点结构:
struct node
{
    void* pdata;
    struct node* prev;
    struct node* next;
};
也就是数据和节点是分开的,数据单独指向一块内存,这样在内存上有点不爽,我们希望数据和节点链域是紧密存放的,这样一个节点内存只分配一次,可是c中没有泛型,怎么让不同数据类型与链域紧密存放呢?
offsetof为我们提供了这样的做法。
offsetof是个宏,之处结构体中某成员的偏移位置。
#define offset(struct_t,member) ((size_t)(char*)((struct_t*)0)->member)
现在我们这样定义链表节点:
struct link
{
    struct link* prev;
    struct link* next;
};
怎么只有链域,没有数据?
别担心,事实上我们把数据存在如下结构中:
struct node
{
    data_t data;
    struct link lnk;
};
这样数据和链域紧密存放,只是链表中仅保存link地址,当需要访问数据时我们可以从link地址减去link在node中的偏移位置offsetof(struct node, struct link)从而得到数据指针。
结构示意如下:

结构示意图
这种做法保证了数据与链域的紧密。不仅用于链表,所有链数据结构如二叉树也可以使用offsetof方式编写。

 

此外还有一种保证紧密性的链结构做法,定义结构如下:

struct item

{

    struct item *next;

    char c;

};

链域在前数据在后,在分配具体节点时分配sizeof(struct item) + sizeof(struct data_t) - 1的大小。