在看nmap的源码中nsock时,对于其中ghlist的设计有些不太懂,so重学链表。
单链表
链表结构
typedef struct Node
{
int data;
struct Node *next;
}NODE, *PNODE;
初始化表头
PNODE pHead;
pHead = malloc(sizeof(struct Node));
pHead->data = 0;
pHead->next =NULL;
创建链表并填值
init_list(PNODE pHead)
{
PNODE p,new;
p = pHead;
int i;
for(i=1;i<10;i++)
{
new = malloc(sizeof(struct Node));//一定要初始化,否则会有段错误提示
new->data = i;
p->next=new;
new->next = NULL;
p = p->next;
}
return 0;
}
打印表格元素
void printf_list(PNODE pHead)
{
PNODE p;
p = pHead;
while(p)
{
printf("%d ",p->data);
p = p->next; //链表操作中最常用,p指针不断向后指
}
printf("\n");
}
在pos位置处添加元素
add_list(PNODE pHead, int pos,int data)
{
PNODE p,temp,new;
p = pHead;
int i= 0;
while(i<pos&&p->next!=NULL)
{
i++;
p=p->next; //直到找到pos位置处的元素
}
new = malloc(sizeof(struct Node));
new->data = data;
new->next=p->next->next;//将new插入到p->next处
p->next = new;
}
双链表
链表结构
typedef struct Node
{
int data;
struct Node *next;
struct Node *pre;
}NODE;
创建链表
Node *pHead = malloc(sizeof(struct Node));
pHead->data = 0;
pHead->pre=NULL;
pHead->next = NULL;
Node pTail = pHead;
插入节点
Node pNew = malloc(sizeof(struct Node));
pNew->data = val;
pNew->next = p->next;//要在p之后插入pNew
p->next = pNew;
nmap中,nsock/src/gh_list.c中将双链表用于存储事件。
链表结构
typedef struct gh_list_elem {
void *data;
struct gh_list_elem *next;//双链表的下一个
struct gh_list_elem *prev;
int allocated;
#ifndef NDEBUG
unsigned long magic;
#endif
} gh_list_elem;
typedef struct gh_list {
/* Number of elements in the list */
int count;
struct gh_list_elem *first;//链表头
struct gh_list_elem *last;
/* Instead of free()ing elements when something is removed from the list, we
* stick them here for the next insert. */
struct gh_list_elem *free;
/* The number of list elements in the most recent malloc */
int last_alloc;
#ifndef NDEBUG
unsigned long magic;
#endif
} gh_list;
在链表结尾处增加节点
gh_list_elem *gh_list_append(gh_list *list, void *data) {
gh_list_elem *newelem;
gh_list_elem *oldlast;
SAFETY_CHECK_LIST(list);
newelem = get_free_buffer(list);
oldlast = list->last;
if (oldlast) {
oldlast->next = newelem;//添加到最后一个位置
newelem->prev = oldlast;
} else {
newelem->prev = NULL;
}
newelem->next = NULL;
newelem->data = data;
#ifndef NDEBUG
newelem->magic = GH_LIST_MAGIC;
#endif
list->count++;
list->last = newelem;
if (list->count == 1)
list->first = newelem;
return newelem;
}
这个函数不明白
static inline struct gh_list_elem *get_free_buffer(struct gh_list *list) {
struct gh_list_elem *newelem;
int i;
if (!list->free) {
list->last_alloc *= 2;
list->free = (struct gh_list_elem *)safe_malloc(list->last_alloc * sizeof(struct gh_list_elem));
memset(list->free, 0, list->last_alloc * sizeof(struct gh_list_elem));
list->free->allocated = 1;
for (i=0; i < list->last_alloc - 1; i++) {
(list->free + i)->next = list->free + i + 1;//这样的方法一般会发生段错误,应该是开辟了一个空间,为什么要这么开,貌似是开辟的时候让链表依然相连?留着以后解决吧,看不懂
}
}
newelem = list->free;
list->free = list->free->next;
#ifndef NDEBUG
newelem->magic = GH_LIST_MAGIC;
#endif
return newelem;
}