C ++获取条目的结构(C++ get struct for an entry)

编程入门 行业动态 更新时间:2024-10-23 18:35:33
C ++获取条目的结构(C++ get struct for an entry)

我在学习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; } } ......

I encounter the following code when I am learning data structures and algorithms in C++. It is from https://github.com/xtaci/algorithms/blob/master/include/double_linked_list.h line 194 to 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

The comment block says the functionality of this Marco is to get the struct for this entry. What puzzles me is the use of

reinterpret_cast<type *>(1)->member

What does it mean by converting 1 to (type *) and access its member?

* Thanks for the help in advance. If any part is not clear, I will edit it quickly. *

* More information *:

This Marco is used in the code to define new 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))

And an example usage of the new Marco is from https://github.com/xtaci/algorithms/blob/master/include/graph_defs.h line 45 to 51 as part of the destructor.

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)告诉编译器有一个type *指针,其地址为0x1 ,然后&(reinterpret_cast<type *>(1)->member)获取&(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("%p\n%p\n", v, w); return 0; }

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

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

this statement if something like Macro offsetof, using to get the offset address of a member in the struct.

the tricky reinterpret_cast<type *>(1) tells the compiler there is a type * pointer whose address is 0x1, then &(reinterpret_cast<type *>(1)->member) gets the offset address of the member plus the original 0x1

I've used code below to verify it.

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; }

it prints 0x9, exactly 2*sizeof(int) + 1

Personally I think using 1 instead of 0 can avoid compiler treats it as an invalid NULL pointer. So in the macro, the 1 is plus again in the tail.

The macro list_entry can be used like this

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; }

when we only have the pointer to list_head we can use list_entry to get the outer struct. In the above code, v and w points to the same area.

更多推荐

本文发布于:2023-08-04 23:32:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1424507.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:目的   结构   entry   struct

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!