C ++获取条目的结构

时间:2015-09-18 06:33:51

标签: c++ struct

在学习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))

新Marco的示例用法是从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;
                }
            }
            ......

1 个答案:

答案 0 :(得分:1)

&(reinterpret_cast<type *>(1)->member)

此语句是否类似于宏offsetof,用于获取结构中成员的偏移地址。

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

我已使用下面的代码进行验证。

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可以避免编译器将其视为无效的NULL指针。所以在宏观中,0在尾部再次加上。

1可以像这样使用

list_entry

当我们只有指向int main() { Vertex *v = (Vertex *) malloc(sizeof(Vertex)); Vertex *w = list_entry(&(v->v_node), Vertex, v_node); printf("%p\n%p\n", v, w); return 0; } 的指针时,我们可以使用list_head来获取外部结构。在上面的代码中,list_entryv指向同一区域。