C 列表头:如果从第二个元素开始解析,则获取垃圾
我在我的C项目列表头结构中使用来定义一个链接列表。在某些情况下,我需要从第二个元素解析列表,但在本例中,我会得到一个额外的元素和一个垃圾值。我试着在我的电脑里用一个小程序来模拟同样的场景。我也有同样的问题:C 列表头:如果从第二个元素开始解析,则获取垃圾,c,linux,list,linked-list,garbage,C,Linux,List,Linked List,Garbage,我在我的C项目列表头结构中使用来定义一个链接列表。在某些情况下,我需要从第二个元素解析列表,但在本例中,我会得到一个额外的元素和一个垃圾值。我试着在我的电脑里用一个小程序来模拟同样的场景。我也有同样的问题: #include<stdio.h> #include<stdlib.h> #include "list.h" struct struct_report{ struct list_head list; char *report; };
#include<stdio.h>
#include<stdlib.h>
#include "list.h"
struct struct_report{
struct list_head list;
char *report;
};
//Add an element to the linked list
void add_report_to_list(struct list_head *reports, char *report) {
struct struct_report *report_strct;
report_strct = calloc(1, sizeof(struct struct_report));
list_add_tail(&report_strct->list, reports);
report_strct->report= strdup(report);
}
int main() {
struct struct_report *retreport;
LIST_HEAD(reports); //instantiate a struct list_head instance
add_report_to_list(&reports, "elt1");
add_report_to_list(&reports, "elt2");
add_report_to_list(&reports, "elt3");
add_report_to_list(&reports, "elt4");
list_for_each_entry(retreport, &reports, list){
printf("============> no next retreport: %s\n", retreport->report);
}
printf("\n");
list_for_each_entry(retreport, reports.next, list){
printf("============> Next retreport: %s\n", retreport->report);
}
return 1;
}
很明显,在我从第一个元素开始正常解析的情况下,我没有任何问题。但是如果我从列表中的第二个元素开始,我会得到一个额外的元素,它的值很奇怪,比如垃圾
有什么解释为什么我会得到一个额外的元素吗?以及如何将其修复为解析到elt4?如果从列表的第一个元素开始(而不是从头部开始),则每个条目的
列表将停止在同一个列表对象中,因为它是循环列表
因此,每个条目()的列表将通过头部。并且头部没有连接到条目。所以当你试图引用头部列表中的条目时,你会得到垃圾
解决方案:从列表的开头开始循环,跳过第一个元素。列表实现实际上创建了一个环。列表头是一个虚拟元素,它将next
指向第一个元素,将prev
指向最后一个元素。(最初两者都指向列表头本身。)在尾部添加元素实际上是在“列表头之前”添加元素。当在这个环上循环时,头部由一个指向它的单独指针标记。没有其他方法将其与列表中的其他元素区分开来
list\u for\u中的for
循环每个\u条目
都与head
指针进行比较,作为循环条件,因此当它再次到达作为列表头提供的对象时,它将停止
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
宏list\u first\u entry
和list\u next\u entry
使用宏container\u of
返回指向用户定义结构的指针,该结构应包含struct list\u head
如果将reports.next
而不是reports
传递到列出每个条目的列表()
,它将把它作为虚拟列表头元素,并将环中的所有其他元素视为真实列表条目
您的代码为尾部元素后面的元素打印垃圾,因为这是一个纯struct list\u head
,它未嵌入struct struct\u报表
,因此宏list\u next\u条目
返回指向main()中struct list\u head报表
之前的内存指针
这是未定义的行为
如果您的程序没有崩溃,如果您通过例如reports.next->next
,您将在elt4
之后得到相同的垃圾。在这种情况下,我希望输出如下:
=============>下一次重新报告:elt3
==========>下一次更新报告:elt4
==========>下一次报告:
==========>下一次更新报告:elt1
而相同的类型—列表头
用于以下两种:
- 名单头
- 列出元素
它们是不可互换的。如果某个宏希望列表头作为参数,则需要提供指向列表头的指针,而不是指向列表元素的指针
宏list\u for\u每个\u条目
接受指向列表头的指针作为第二个参数,因此不应将指针传递给元素
对于在列表上迭代时跳过第一个元素,宏
列出来自的每个条目的列表
列出每个条目的列表\u继续
或
可以使用
这两个宏对每个条目采用与列表相同的参数,但它们考虑了光标的初始值(第一个参数):
list\u for\u来自
的每个条目在光标指向的元素处开始迭代
list\u for\u每个条目继续
在光标指向的元素之后开始迭代
因此,在列表上迭代并跳过第一个元素可能如下所示:
// Set cursor to the first element in the list
retreport = list_first_entry(reports, typeof(*retreport), list);
// Iterate starting after the cursor
list_for_each_entry_continue(retreport, reports, list){
printf("============> Next retreport: %s\n", retreport->report);
}
什么是列表头(报告)代码>?.next
字段未在任何位置定义。什么是每个条目的列表()?每个条目(…){printf…}的部分“列表”看起来很奇怪。请您的问题添加此信息,而不是添加注释。请为每个条目显示list\u的定义function和struct list\u head
structure@Bodo负责人名单(报告);实例化结构列表\u head rports变量。接下来是列表头中的一个属性:struct list头{struct list头*next;struct list头*prev;}@RishikeshRaje@KallelOmar请回答您的问题,并在问题中添加所有信息,而不是写评论。
// Set cursor to the first element in the list
retreport = list_first_entry(reports, typeof(*retreport), list);
// Iterate starting after the cursor
list_for_each_entry_continue(retreport, reports, list){
printf("============> Next retreport: %s\n", retreport->report);
}