C++获取条目的结构

C++ get struct for an entry

本文关键字:结构 获取 C++      更新时间:2023-10-16

我在C++中学习数据结构和算法时遇到以下代码。它来自https://github.com/xtaci/algorithms/blob/master/include/double_linked_list.h线194到206。

/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:   the type of the struct this is embedded in.
 * @member: the name of the list_struct within the struct.
 */
#ifndef _MSC_VER
#define list_entry(ptr, type, member) 
    (reinterpret_cast<type *>((char *)(ptr)-(char *)(&(reinterpret_cast<type *>(1)->member))+1))
#else
#define list_entry(ptr, ptrtype, member) 
    (reinterpret_cast<ptrtype>((char *)(ptr)-(char *)(&(reinterpret_cast<ptrtype>(1)->member))+1))
#endif

注释块表示这个Marco的功能是获取这个条目的结构。令我困惑的是的使用

reinterpret_cast<type *>(1)->member

将1转换为(类型*(并访问其成员是什么意思?

*感谢您提前提供的帮助。如果有任何部分不清楚,我会迅速编辑*

*更多信息*:

这个Marco在代码中用于定义新的Marco

#define list_for_each_entry_safe(pos, n, head, member)          
    for (pos = list_entry((head)->next, typeof(*pos), member),  
        n = list_entry(pos->member.next, typeof(*pos), member); 
         &pos->member != (head);                    
         pos = n, n = list_entry(n->member.next, typeof(*n), member))

新马可的用法示例来自https://github.com/xtaci/algorithms/blob/master/include/graph_defs.h第45至51行作为析构函数的一部分。

        struct Adjacent {
            struct Vertex v;
            int32_t color;  // color for searching
            int32_t d;  // discover time
            int32_t f;  // finish time
            struct list_head v_head;  // vertex list header
            struct list_head a_node; 
            uint32_t num_neigh;     // num of neighbours
            Adjacent(uint32_t id):v(id) {
                INIT_LIST_HEAD(&v_head);
                num_neigh = 0;
            }
            ~Adjacent() {
                Vertex * v, *vn;
                list_for_each_entry_safe(v, vn, &v_head, v_node){
                    list_del(&v->v_node);
                    delete v;
                }
            }
            ......
&(reinterpret_cast<type *>(1)->member)

如果类似于Macro offsetof,则使用此语句获取结构中成员的偏移地址。

棘手的reinterpret_cast<type *>(1)告诉编译器有一个地址为0x1type *指针,然后&(reinterpret_cast<type *>(1)->member)得到成员的偏移地址加上原始的0x1

我用下面的代码来验证它。

struct list_head {
    struct list_head *next, *prev;
};
struct Vertex {
    int x;
    int y;
    list_head v_node;
};
int main()
{
    Vertex *v = (Vertex *) malloc(sizeof(Vertex));
    printf("%p", &(reinterpret_cast<Vertex *>(1)->v_node));
    return 0;
}

它打印0x9,确切地说是2*sizeof(int) + 1

我个人认为使用1而不是0可以避免编译器将其视为无效的NULL指针。因此,在宏中,1在尾部再次为正。

list_entry可以像这个一样使用

int main()
{
    Vertex *v = (Vertex *) malloc(sizeof(Vertex));
    Vertex *w = list_entry(&(v->v_node), Vertex, v_node);
    printf("%pn%pn", v, w);
    return 0;
}

当我们只有指向list_head的指针时,我们可以使用list_entry来获取外部结构。在上述代码中,vw指向同一区域。