前几天看了一个程序,里面一段关于指针的代码让我非常纠结,看了很久才看懂,在这里将将其记录下来,希望能对大家有一定的帮助,先看示例程序(编译器gcc):
#include
#include
#include
typedef struct list_node
{
int data;
struct list_node *next;
}list_node, list, *plist_node;
static list *lst = NULL;
void insert(int dat)
{
plist_node pnode = malloc(sizeof(list_node));
assert(pnode != NULL);
pnode->data = dat;
pnode->next = lst;
lst = pnode;
}
int remove_item(int dat)
{
int cnt = 0;
plist_node pn, *ppn;
ppn = &lst;
while((pn = *ppn) != NULL)
{
if(pn->data == dat)
{
*ppn = pn->next;
free(pn);
++cnt;
}
else
{
ppn = &(pn->next);
}
}
return cnt;
}
void print_list()
{
plist_node pn;
pn = lst;
while(pn != NULL)
{
printf("%d ", pn->data);
pn = pn->next;
}
printf("\n");
}
int main()
{
int cnt;
int i;
int arr[10] = {1, 6, 3, 1, 9, 2, 1, 3, 6, 1};
for(i = 0; i < 10; i++)
{
insert(arr[i]);
}
print_list();
cnt = remove_item(1);
print_list();
printf("%d\n", cnt);
return 0;
}
本文主要要讲的内容主要是remove_item函数中的两句:a、*ppn = pn->next; b、ppn = &(pn->next),乍一看这两句不是他妈的一个意思吗?怎么就实现了删除呢?
分析:
为了方便叙述(实际上是为了少打点字),在下面的叙述中做一些简化,如6的next的指针是指链表中data域为6的项的next指针的指针
在main函数中,链表插入完成后为:1 6 3 1 2 9 1 3 6 1
在删除第一个1时,*ppn = lst,pn = lst,所以,在执行a后,lst指向了6;接着由于if语句不成立,将执行b,在执行完b后,ppn指向的是6的next的指针,如此一直到链表中第二个1时,ppn指向的是前一项的next的指针(3的next的指针),这是if条件满足,执行a,此时实际上是将3的next指针指向1的下一项,而pn指向的又是1所在的项,这样就可以完成第二个1的删除。以此类推就可以完成对1的所有删除。
是不是有点晕了,总之我是有点晕了,表述的不好,求文采好的同学修饰一下这段文字,使其更容易理解。