I want to change the world, but I can't find the source code.
想改变世界,但找不到源代码,这的确比较凄凉。但是如果源代码就在那里,只不过你没去看,那更是悲哀。
昨天在cool shell上看到一篇文章(http://coolshell.cn/articles/8990.html),主要讲述如何利用二级指针删除单向链表。代码如下:
View Code
1 void remove_if(node ** head, remove_fn rm) 2 { 3 for (node** curr = head; *curr; ) 4 { 5 node * entry = *curr; 6 if (rm(entry)) 7 { 8 *curr = entry->next; 9 free(entry); 10 } 11 else 12 curr = &entry->next; 13 } 14 }
然后对比一下传统的做法:
View Code
1 typedef struct node 2 { 3 struct node * next; 4 .... 5 } node; 6 7 typedef bool (* remove_fn)(node const * v); 8 9 // Remove all nodes from the supplied list for which the 10 // supplied remove function returns true. 11 // Returns the new head of the list. 12 node * remove_if(node * head, remove_fn rm) 13 { 14 for (node * prev = NULL, * curr = head; curr != NULL; ) 15 { 16 node * const next = curr->next; 17 if (rm(curr)) 18 { 19 if (prev) 20 prev->next = next; 21 else 22 head = next; 23 free(curr); 24 } 25 else 26 prev = curr; 27 curr = next; 28 } 29 return head; 30 }
差距在哪里呢?针对这两段代码来说,是1.没有认识到head指针和node->next其实是同一样东西(struct node*,指向下一个等处理的元素),2.可以统一使用二级指针来处理。再本质一点,也就是用linus大婶的话来说,不懂指针。
显然我现在还没有到懂指针的水平,可能懂指针之后就会很自然地想到,删除单向链表,其实就是操作一个node->next链表(包括head),也就是说,遍历一下这个链表就可以了,那么怎样遍历呢?用一个指针指向链表的头,然后遍历。在这里就表现为一个二级指针。
这段代码实践上的意义比理论上的意义要真切得多,所以,还是多看源代码吧。在内核里面,这种代码比比皆是。