Pointer
===
---
###### tags: `C`
找到一段創世神 Linus Torvalds 對於 pointer 發表的言論,覺得蠻有趣的紀錄一下
https://meta.slashdot.org/story/12/10/11/0030249/linus-torvalds-answers-your-questions
你如果覺得你很會用 Pointer 的話,可以看看這篇,驗證一下你的答案。
---
> At the opposite end of the spectrum, I actually wish more people understood the really core low-level kind of coding. Not big, complex stuff like the lockless name lookup, but simply good use of pointers-to-pointers etc. For example, I've seen too many people who delete a singly-linked list entry by keeping track of the "prev" entry, and then to delete the entry, doing something like
>
> if (prev)
prev->next = entry->next;
else
list_head = entry->next;
>
> and whenever I see code like that, I just go "This person doesn't understand pointers". And it's sadly quite common.
>
> People who understand pointers just use a "pointer to the entry pointer", and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing a "*pp = entry->next".
Google 了一下,找到一個解釋得很好的文章,以下摘錄 code
https://grisha.org/blog/2013/04/02/linus-on-understanding-pointers/
假設有一個 singly-linked list
```c=
typedef struct list_entry {
int val;
struct list_entry *next;
} list_entry;
```
如果要砍掉 val == to_remove 的所有 entries,有兩種寫法,哪個比較好,看 code 就知道
```c=
list_entry *entry = head; /* assuming head exists and is the first entry of the list */
list_entry *prev = NULL;
while (entry) {
if (entry->val == to_remove) /* this is the one to remove */
if (prev)
prev->next = entry->next; /* remove the entry */
else
head = entry->next; /* special case - first entry */
/* move on to the next entry */
prev = entry;
entry = entry->next;
}
```
```c=
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
while (entry) {
if (entry->val == to_remove)
*pp = entry->next;
pp = &entry->next;
entry = entry->next;
}
```
不過看到了 kernel 中 `find_vma_links` 的寫法後,又學到了可以再簡寫成
```c=
list_entry **pp = &head;
while (*pp) {
if ((*pp)->val == to_remove)
*pp = (*pp)->next;
pp = &entry->next;
}
```