# 2019-06-19 王議偉
contributed by < `yiwei01` >
## Q1: memory alignment
以下程式碼改寫自 Linux 核心,比較兩個 Ethernet MAC 地址是否一致。在特定的硬體平台 (如 Arm 和 MIPS) 可能會遇到 unaligned memory access,請改寫以避開這個問題。考慮輸入值必為 16-bit-aligned addresses
```cpp
#include <stdint.h>
bool addr_equal(const uint8_t *addr1, const uint8_t *addr2)
{
uint32_t fold = ((*(const uint32_t *)addr1) ^ (*(const uint32_t *)addr2)) |
((*(const uint16_t *)(addr1 + 4)) ^ (*(const uint16_t *)(addr2 + 4)));
return fold == 0;
}
```
Hint: 考慮地址是 `0x10003`
Reference:
* [MAC Addresses With Formatting Examples](https://www.lifewire.com/introduction-to-mac-addresses-817937)
## Answer
```cpp
const uint16_t *a = (const uint16_t *)addr1, *b = (const uint16_t *)addr2;
return (0 == (a[0] ^ b[0]) | a[1] ^ b[1] | a[2] ^ b[2]));
```
---
## Q2:
使用 Linux 核心的 [list.h](https://github.com/torvalds/linux/blob/master/include/linux/list.h),寫出對一個已經排序過的 linked list 做新增節點的操作。
Hint: list_empty, list_add, list_for_each_entry, list_add_tail
## Answer
### version 1
```clike=
#include <stddef.h>
#include <stdint.h>
#include "list.h"
struct listitem {
uint16_t i;
struct list_head list;
};
static inline int cmpint(const void *p1, const void *p2) {
const uint16_t *i1 = (const uint16_t *) p1;
const uint16_t *i2 = (const uint16_t *) p2;
return *i1 - *i2;
}
void list_insert_sorted(struct listitem *entry, struct list_head *head)
{
struct listitem *item = NULL;
if (list_empty(head)) {
list_add(&entry->list, head);
return;
}
list_for_each_entry(item, head, list) {
if(item->i > entry->i){
list_add_tail(&entry->list, &item->list);
return;
}
}
list_add(&entry->list, head->next)
}
```
想法是:走訪 linked list 的同時做比較,符合比較的結果便直接插入。
注意:`list_add` 及 `list_add_tail` 的原始碼。
### version 2
```clike=
struct list_head *right = NULL;
INIT_LIST_HEAD(right);
list_for_each_entry_safe (item, is, &testlist, list) {
if(item->i > entry->i){
list_move_tail(&item->list,&right);
}
}
list_add(&entry->list,right);
list_splice_tail(right,head);
```
此版本雖然 worst case 雖然也是 O(n),但與上述 version1 的答案相比,較不直觀。
### 如果不是 circular list,該做哪些額外的檢查?
若不是 circular list ,則必須紀錄 front 及 rear ,因此在程式碼的撰寫上會多一些邊界條件判斷,以確保 front 及 rear 的正確性。
###### tags: `sysprog2019`