# 2025q1 Homework2 (quiz1+2)
contributed by < [Hlunlun](https://github.com/Hlunlun) >
## 第一周
### [測驗 1](https://hackmd.io/@sysprog/linux2025-quiz1#%E6%B8%AC%E9%A9%97-1)
實做 `list_insert_before()` 這個函數,並使用到 [你所不知道的 C 語言: linked list 和非連續記憶體](https://hackmd.io/@sysprog/c-linked-list) 中指標指標的技巧
函數定義的參數有三個指標變數,`l` 指向 `list` ,`before` 指向預添加節點後所連接的節點,`item` 指向預添加節點,三個節點可能會呈現以下
```graphviz
digraph list_type{
rankdir=LR;
node [shape=record];
// Improve edge routing
splines=true;
overlap=false;
l[label="l", shape=none];
l_[label="<ref>list|<head>head"];
n0[label="<ref>n0|{0|<next>next}"]
n1[label="<ref>n1|{1|<next>next}"]
n2[label="<ref>n2|{8|<next>next}"]
item[label="item", shape=none];
item_[label="<ref> n3|{5|<next>next}"];
before[label="before", shape=none];
l->l_:ref;
item -> item_:ref;
before -> n2:ref;
l_:head->n0:ref;
n0:next->n1:ref;
n1:next->n2:ref;
l-> l_ -> n0 -> n1 -> n2 [style=invis];
}
```
`list_insert_before()` 主要功能就是將 `n3` 接在 `n2` 之前
```graphviz
digraph list_type{
rankdir=LR;
node [shape=record];
// Improve edge routing
splines=true;
overlap=false;
l[label="l", shape=none];
l_[label="<ref>list|<head>head"];
n0[label="<ref>n0|{0|<next>next}"]
n1[label="<ref>n1|{1|<next>next}"]
n2[label="<ref>n2|{8|<next>next}"]
item[label="item", shape=none];
n3[label="<ref> n3|{5|<next>next}"];
before[label="before", shape=none];
l->l_:ref;
item -> n3:ref;
before -> n2:ref;
l_:head->n0:ref;
n0:next->n1:ref;
n1:next->n3:ref;
n3:next->n2:ref;
l-> l_ -> n0 -> n1 -> n3 -> n2 [style=invis];
}
```
運用 指標的指標 技巧,首先將指標 `p` 指向指標 `l->head`,指標變數 `p` 中存放的是 指標 `l->head` 的記憶體位置,藉由檢查 `*p` 來避免直接使用空的 `l->head` 進行迭代
```graphviz
digraph list_type{
rankdir=LR;
node [shape=record];
// Improve edge routing
splines=true;
overlap=false;
l[label="l", shape=none];
l_[label="<ref>list|<head>head"];
n0[label="<ref>n0|{0|<next>next}"]
n1[label="<ref>n1|{1|<next>next}"]
n2[label="<ref>n2|{8|<next>next}"]
item[label="item"];
item_[label="<ref> n3|{5|<next>next}"];
before[label="before", shape=none];
p[label="p" fontcolor="red", shape=none];
p->l_:head;
l->l_:ref;
item -> item_:ref;
before -> n2:ref;
l_:head->n0:ref;
n0:next->n1:ref;
n1:next->n2:ref;
l-> l_ -> n0 -> n1 -> n2 [style=invis];
}
```
接下來找到指向 `*before` 的指標,也就是在鍊結串列中進行迭代找到 `n1->next`,而指標的指標可以透過 `&(*p)->next` 取得 `*p` 指向的節點的 `next` 的記憶體位置,直到 `*p` 指向 `*before` 及停止如下圖
```graphviz
digraph list_type{
rankdir=LR;
node [shape=record];
// Improve edge routing
splines=true;
overlap=false;
l[label="l", shape=none];
l_[label="<ref>list|<head>head"];
n0[label="<ref>n0|{0|<next>next}"]
n1[label="<ref>n1|{1|<next>next}"]
n2[label="<ref>n2|{8|<next>next}"]
item[label="item"];
item_[label="<ref> n3|{5|<next>next}"];
before[label="before", shape=none];
p0[label="p", fontcolor="red", shape=none];
p1[label="p", fontcolor="red", shape=none];
p[label="p", fontcolor="red", shape=none];
p0->l_:head[style="dashed"];
p1->n0:next[style="dashed"];
p->n1:next[color="red"];
l->l_:ref;
item -> item_:ref;
before -> n2:ref[color="green"];
l_:head->n0:ref;
n0:next->n1:ref;
n1:next->n2:ref[color="green" label="*p" fontcolor="green"];
l-> l_ -> n0 -> n1 -> n2 [style=invis];
}
```
最後將目前 `p` 指向的指標 `n1->next` 指向 `*item` (也就是 `n3` ),最後用 `n3->next` 將 `*before` (也就是 `n2` ) 接在 `n3` 後面,至此即完成實做 `list_insert_before()`
```graphviz
digraph list_type{
rankdir=LR;
node [shape=record];
// Improve edge routing
splines=true;
overlap=false;
l[label="l", shape=none];
l_[label="<ref>list|<head>head"];
n0[label="<ref>n0|{0|<next>next}"]
n1[label="<ref>n1|{1|<next>next}"]
n2[label="<ref>n2|{8|<next>next}"]
item[label="item"];
n3[label="<ref> n3|{5|<next>next}"];
before[label="before", shape=none];
p[label="p" fontcolor="red", shape=none];
l->l_:ref;
item -> n3:ref;
before -> n2:ref;
l_:head->n0:ref;
n0:next->n1:ref;
n1:next->n3:ref[color="red"];
p->n1:next
n3:next->n2:ref[color="red"];
l-> l_ -> n0 -> n1 -> n2 [style=invis];
}
```
## [測驗2](https://hackmd.io/@sysprog/linux2025-quiz1#%E6%B8%AC%E9%A9%97-2)
## [測驗3](https://hackmd.io/@sysprog/linux2025-quiz1#%E6%B8%AC%E9%A9%97-3)