# 2018q3 Homework1
contributed by < [wingard](https://github.com/wingard) >
## 作業進度表
- [x] [提問的智慧](http://mis.ndhu.edu.tw/docu/question.htm) https://hackmd.io/s/HJpiYaZfl
- [x] [為什麼要深入學習 C 語言?](https://hackmd.io/s/HJpiYaZfl) -- 9/17
- [x] [你所不知道的 C 語言: 指標篇](https://hackmd.io/s/HyBPr9WGl) -- 9/24
- [ ] [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/s/SJ6hRj-zg) -- 9/24
- [ ] [你所不知道的 C 語言: 遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl)
- [ ] [你所不知道的 C 語言: 前置處理器應用篇](https://hackmd.io/s/S1maxCXMl)
- [ ] [你所不知道的 C 語言: goto 和流程控制](https://hackmd.io/s/B1e2AUZeM)
- [ ] [你所不知道的 C 語言: linked list 和非連續記憶體操作](https://hackmd.io/s/SkE33UTHf) -- 9/22
- [ ] [你所不知道的 C 語言:技巧篇](https://hackmd.io/s/HyIdoLnjl)
- [x] [GNU/Linux 開發工具](https://hackmd.io/c/rJKbX1pFZ): -- 9/18
務必==自主學習 Linux 操作== (當然你需要安裝 Linux 作業系統到自己的電腦中,每天都用 Linux,就會變強), Git, HackMD, LaTeX 語法 (特別是數學式), GNU make, perf, gnuplot
---
## [為什麼要深入學習 C 語言?(開發工具和規格標準)](https://hackmd.io/s/HJFyt37Mx)
### 重點
### 專注討論 C 語言而不探討 C++ 語言的原因
* C++ 發展過於快速
* C 與 C++ 的差異(在1999年之後,就各自發展):
* [Designated Initializers](https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html) 只在 C 語言支援,C++ 不支援
* 對於 [lvalue](https://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c) 的解釋不同
* 關於 C11 與 C++14 的新增功能
### 軟體授權條款
* 因應GPL 授權的感染效應問題,libc 有了其他的開發專案
* 例如 [musl libc](https://www.musl-libc.org/),[念為](hhttps://www.musl-libc.org/faq.html) "muscle " libc
* 軟體授權條款,節錄如下
* [MIT License](https://www.openfoundry.org/tw/legal-column-list/513--mit) : 最寬鬆,只要將 MIT License 的文字內容以及專案作者的著作權聲明附隨和軟體一併釋出即可。(軟體可為binary或source code形式釋出)
* [BSD License](https://www.openfoundry.org/index.php?option=com_content&task=view&id=524&Itemid=56) : 只要在後續作品中保留原專案作者的著作權聲明 (copyright notice) 及其免責聲明 (disclaimer) 這兩項義務性規範的要求,則可以自由地使用、改作、重製,及散布這些以 BSD-3-Clause License 授權的程式。 (BSD 2-clause 幾乎等價於 MIT License)
* [GPL License](https://www.openfoundry.org/index.php?option=com_content&task=view&id=525&Itemid=56) : 最嚴格,其授權擴散規則,像是病毒一般具有感染效應 (viral effect),會將同一專案裡的其他元件也感染成為 GPL 的授權狀態。
* [GCC Runtime Library Exception Rationale and FAQ](https://www.gnu.org/licenses/gcc-exception-3.1-faq.html)
### 學習心態
* [這時代的專業不再有明確的疆界,生涯不再有明確的階段。你做的每件事都應該同時是工作、學習與生活。](https://twitter.com/hao520/status/863971655193735168)
### C 語言與 Linux Kernel
* C 語言是高階的組合語言
* Linux Kernel 是個高度物件導向的 C 語言開發專案,裡面有許多經典的設計思維
* 學習 C 語言,要查閱[規格書](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)(第一手資料)
* `&`: 唸作 address of
* `*`: 唸作 value of (也稱作 indirection operator )
### GDB 初探
* [Compiler Bootstraping](https://en.wikipedia.org/wiki/Bootstrapping_(compilers)) : 從頭開始打造一個self-compiling compiler
* 老師有實作一個 [AMaCC](https://github.com/jserv/amacc) Compiler
* gdb debug: 使用 [DWARF](https://www.ibm.com/developerworks/aix/library/au-dwarf-debug-format/index.html) 格式
* compile 時要加入 `-g` 來產生debug info
* [Mozilla rr](https://github.com/mozilla/rr) 是作 [Application Checkpointing](https://en.wikipedia.org/wiki/Application_checkpointing)
:::info
既然你都留意到 rr,之後專案開發就拿來用吧
:notes: jserv
:::
### 心得
* cdecl 除了安裝套件,也有[線上](https://cdecl.org/)的服務
* 要會善用,首先得熟悉規格書常用的英文單字
* designated: 指定,選定;委派
* declare: 宣告
* cast: 型別轉換
### 提問
:::warning
1. 覺得 C99 規格書文字內容很生硬,不易完全理解其中意涵,請問該如何入門?
2. 影片有提到GCC是具有工業強度的編譯器,請問是指GCC有通過業界對於編譯器的相關認證嗎?
:::
:::info
你需要耐心!列出具體你看不懂的段落出來,逐一討論
:notes: jserv
:::
---
## [你所不知道的 C 語言: 指標篇](https://hackmd.io/s/HyBPr9WGl)
#### C 語言當初設計的用途
* 開發 UNIX 作業系統
* 能充分掌握硬體資源(記憶體,暫存器)
* 與其說是程式語言,不如說是一種思維方式
* C 語言代表的文化是 UNIX ,甚至可以說是 UNIX 的母語
* 在 UNIX 開發過程中逐步演化
* Go 語言花很多時間討論 Concurrency / 多執行緒
* 透過系統程式語言處理資源同步與衝突問題
* C 語言的編譯器,可以自己編譯自己
* Ruby 語言則無法,需要透過其他語言來開發直譯器
* [指標教學範例](https://hellolynn.hpd.io/2017/05/15/c%E8%AA%9E%E8%A8%80-%E8%B6%85%E5%A5%BD%E6%87%82%E7%9A%84%E6%8C%87%E6%A8%99%EF%BC%8C%E5%88%9D%E5%AD%B8%E8%80%85%E8%AB%8B%E9%80%B2%EF%BD%9E/)內的區域變數(int a = 15 ...int e = 67),其對應的記憶體位址未必是照順序排的; 排序方式與編譯器及編譯時的參數設定有關
* qsort()
* glibc 的實作
* 數量大時,用 quicksort
* 數量小時,用 insertion sort
* comparison 的方式,是透過 function pointer 的方式帶入
```clike
int (*compar)(const void *, const void *)
```
* 了解規格書的好處
* 可以針對 compiler bug 作深入討論
* 討論 undefined behavior
* C 語言可以宣告一個 incomplete type,不能從incomplete type宣告一個 instance,但可以從incomplete type 宣告一個 pointer
```clike
//declare
struct GraphicObject;
struct GraphicObject X; //Compile NG
struct GraphicObject *X; //Compile OK
```
* 因為不希望記憶體位址被修改(但位址對應的內容可以被修改),故以下 source code 加上了 const 這個 qualifier
* 變成 Lvalue 之後,就是可以存取的資源; L 代表 locator 的意思
```clike
*(int32_t * const) (0x67a9) = 0xaa6;
/* Lvalue */
```
* 在以下的程式碼,由於main預設會回傳int,故short int return出來的資訊會被截斷 ( int -> short int )
```C
main()
{
}
short int X()
{
return main();
}
```
### "指標的指標"
* 用於延伸原本function內變數的生命週期
* 由於變數 p增加了一個 `*` (dereference),其對應變數的生命週期 (lifetime) 就擴張到 func 的上一層使用範圍內
```C=1
//p will be destroyed when func exits
int B = 2;
void func(int *p) { p = &B; }
int main() {
int A = 1, C = 3;
int *ptrA = &A;
func(ptrA);
printf("%d\n", *ptrA);
return 0;
}
// p will be kept
int B = 2;
void func(int **p) { *p = &B; }
int main() {
int A = 1, C = 3;
int *ptrA = &A;
func(&ptrA);
printf("%d\n", *ptrA);
return 0;
}
```
* C 語言與硬體的對應
* Function Call 對應 Stack Pointer
* 資料傳遞透過暫存器
* 指標被創造出來,不是只為了存取記憶體,而是可以創造出彈性的資料結構
* 例如 Linked List ,在 Struct 內做修改,便可以從單向變成雙向
### Pointer & Array
* C語言內沒有真正的陣列/矩陣,陣列只是一個語法糖
* Array subscripting
> [C99 Section 6.5.2.1] A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).
* Pointer 與 Array 並非在所有的狀態下都是等價
* 使用 `extern` 作為宣告時,不能轉成pointer
```
extern int *x; // declare x to be a pointer of int
extern int x[]; // declare x to be an array of int of incomplete type (unspecified size)
```
* Array 宣告成固定長度時,不能轉成pointer
* `x[i]` 、 `*(x + i)` 、 `*(i + x)` 、 `i[x]` 四項是等價的
* 注意 `i[x]` 比較少見
* ```int* ptr, value;```
* ptr 宣告為 pointer to int ,**但 value 宣告為 int 而不是 pointer to int**
* 此表示法容易讓 value 宣告型態被搞混,建議改成```int *ptr, value;```
* 根據你使用的地方不同,Array 會有不同的意義:
* 如果是用在 expression,array 永遠會被轉成一個 pointer
* 用在 function argument 以外的 declaration 中它還是一個 array,而且「不能」被改寫成 pointer
* function argument 中的 array 會被轉成 pointer
* 使用GDB的前置作業
* `-Og`: 產生 compiler friendly 的執行檔
> [GCC man page] If you are not using some other optimization option, consider using -Og with -g. With no -O option at all, some compiler passes that collect information useful for debugging do not run at all, so that -Og may result in a better debugging experience.
```
$ gcc -o s -Og -g s.c
$ gdb -q s
```
### int main(int argc, char *argv[], char *envp[])
* argc: argument的數量
* argv: 所有 argument 的string vector
* envp: environment variable
* argc 跟 argv 是在 shell fork 之前填入,原因是在於這樣可以適用排程器在讓 child process 比 parent process 先執行的狀況
### malloc()
* strlen() 是在執行時期才會確認回傳值,故以下的 strlen(s) + strlen(t) 有可能是 0
* 由於 malloc 失敗時會回傳NULL,但 malloc(0) 也有可能回傳 NULL,故以下的 code 在判斷上會可能出錯,會導致strcpy / strcat 對 NULL pointer 操作而產生問題
```C
char *r = malloc(strlen(s) + strlen(t));
strcpy(r, s); strcat(r, t);
```
[malloc(0) 有可能會回傳 NULL 的 man page 節錄](http://man7.org/linux/man-pages/man3/malloc.3.html)
> If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
* 以下是一個小技巧:將需要 malloc 的 size 大小**增加 1**,就可以避開 malloc(0) 的情況
```C
char *r = malloc(strlen(s) + strlen(t) + 1); // use sbrk; change progrram break
if (!r) exit(1); /* print some error and exit */
strcpy(r, s); strcat(r, t);
```
* strdup() 也會有類似的問題
* 使用 strcpy() 程式設計者要同時準備好來源字串和目的字串的記憶體空間, 而 strdup() 只需傳入來源字串, 它會另外去 malloc 一塊記憶體, 並複製來源字串後傳回. 使用 strdup() 程式設計者要記得去 free() 傳回的空間.
* 由於 malloc 有可能會失敗(回傳 NULL ),此時若沒有檢查傳回空間的正確性,就直接操作的話,有可能會發生錯誤
```C=1
char *p, *q;
p = strdup("xyz");
q = p;
q[1] = "A";
```
### Function Pointer
*
### 提問
:::warning
1. 不確定[影片](https://youtu.be/G7vERppua9o?t=1h49m34s)內的 "true > ptr.c" 指令的用途
:::
:::info
讓檔案 `ptr.c` 內容清空
:notes: jserv
:::
---
## [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/s/SJ6hRj-zg)
### Nested Function
* 在 function 內部,定義另外一個function (如同區域變數一般)
* 常見用來實做 callback function
* Example: [Swift 語言 nested function 的討論](https://stackoverflow.com/a/30354666/500983)
> a function in a function has the local environment in scope. Code inside the nested function can "see" local variables declared before the nested function declaration. This can be much more convenient and natural than passing a bunch of parameters.
```
func checkPair(_ p1:Piece, and p2:Piece) -> Path? {
// ...
func addPathIfValid(_ midpt1:Point, _ midpt2:Point) {
// ...
}
for y in -1..._yct {
addPathIfValid((pt1.x,y),(pt2.x,y))
}
for x in -1..._xct {
addPathIfValid((x,pt1.y),(x,pt2.y))
}
// ...
}
```
* C 語言不支援的原因,是為了簡化編譯器的設計
* 以下是最接近 nested function 的版本,
在 function f 內宣告 function g,另外在 upper level 定義 function g
``` C=1
void f(void)
{
// Declare a function called g
void g(void);
// Call g
g();
}
// Definition of g
void g(void)
{
}
```
* [GCC 透過 extension 額外支援 nested function ](https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html)
> Nested functions are supported as an extension in GNU C, but are not supported by GNU C++.
> The nested function can access all the variables of the containing function that are visible at the point of its definition. This is called lexical scoping. For example, here we show a nested function which uses an inherited variable named offset:
```C
bar (int *array, int offset, int size)
{
int access (int *array, int index)
{ return array[index + offset]; }
int i;
/* … */
for (i = 0; i < size; i++)
/* … */ access (array, i) /* … */
}
```
* MMIO: 將實體週邊對應到記憶體位址,當作一般記憶體去存取
* Symbol: 將人類所看懂的變數對應到位址
* Parameter 在意的是數值本身
* .data: 放置的是機械碼 `.` 表示 segment
* 改變區段的範圍 : program break
```bash
kevin@T470:~/Documents/DYKC/Function$ ./sleep
^Z
[1]+ Stopped ./sleep
kevin@T470:~/Documents/DYKC/Function$ bg
[1]+ ./sleep &
kevin@T470:~/Documents/DYKC/Function$ ps aux | grep sleep
kevin 19687 0.0 0.0 4376 816 pts/0 S 10:30 0:00 ./sleep
kevin 19696 0.0 0.0 21832 1036 pts/0 S+ 10:31 0:00 grep --color=auto sleep
kevin@T470:~/Documents/DYKC/Function$ ls /proc/19687
attr exe mounts projid_map status
autogroup fd mountstats root syscall
auxv fdinfo net sched task
cgroup gid_map ns schedstat timers
clear_refs io numa_maps sessionid timerslack_ns
cmdline limits oom_adj setgroups uid_map
comm loginuid oom_score smaps wchan
coredump_filter map_files oom_score_adj smaps_rollup
cpuset maps pagemap stack
cwd mem patch_state stat
environ mountinfo personality statm
kevin@T470:~/Documents/DYKC/Function$ cat /proc/19687/maps
558605352000-558605353000 r-xp 00000000 103:06 142702 /home/kevin/Documents/DYKC/Function/sleep
558605552000-558605553000 r--p 00000000 103:06 142702 /home/kevin/Documents/DYKC/Function/sleep
558605553000-558605554000 rw-p 00001000 103:06 142702 /home/kevin/Documents/DYKC/Function/sleep
7f87dd01b000-7f87dd202000 r-xp 00000000 103:06 137108 /lib/x86_64-linux-gnu/libc-2.27.so
7f87dd202000-7f87dd402000 ---p 001e7000 103:06 137108 /lib/x86_64-linux-gnu/libc-2.27.so
7f87dd402000-7f87dd406000 r--p 001e7000 103:06 137108 /lib/x86_64-linux-gnu/libc-2.27.so
7f87dd406000-7f87dd408000 rw-p 001eb000 103:06 137108 /lib/x86_64-linux-gnu/libc-2.27.so
7f87dd408000-7f87dd40c000 rw-p 00000000 00:00 0
7f87dd40c000-7f87dd433000 r-xp 00000000 103:06 137080 /lib/x86_64-linux-gnu/ld-2.27.so
7f87dd617000-7f87dd619000 rw-p 00000000 00:00 0
7f87dd633000-7f87dd634000 r--p 00027000 103:06 137080 /lib/x86_64-linux-gnu/ld-2.27.so
7f87dd634000-7f87dd635000 rw-p 00028000 103:06 137080 /lib/x86_64-linux-gnu/ld-2.27.so
7f87dd635000-7f87dd636000 rw-p 00000000 00:00 0
7ffe0de41000-7ffe0de62000 rw-p 00000000 00:00 0 [stack]
7ffe0dfc4000-7ffe0dfc7000 r--p 00000000 00:00 0 [vvar]
7ffe0dfc7000-7ffe0dfc9000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
```
* rwxp
* r: 可讀
* w: 可寫
* x: 可執行
* p: private
* libc: C 語言標準函式庫的實做
* ld: dynamic linker
### 提問
:::warning
1. 既然 nested function 在 GCC 已經以 extension 的方式支援了,有可能直接整合到最新 C 語言標準的一部分嗎?
:::
---
## [你所不知道的 C 語言: 遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl)
### 重點
*
### 心得
*
### 提問
:::warning
:::
---
## [你所不知道的 C 語言: 前置處理器應用篇](https://hackmd.io/s/S1maxCXMl)
### 重點
*
### 心得
*
### 提問
:::warning
:::
---
## [你所不知道的 C 語言: goto 和流程控制](https://hackmd.io/s/B1e2AUZeM)
### 重點
*
### 心得
*
### 提問
:::warning
:::
---
## [你所不知道的 C 語言: linked list 和非連續記憶體操作](https://hackmd.io/s/SkE33UTHf)
### 從 linked list 刪除節點,看程式設計的品味
* 將實做的角度,從處理物件(head & non-head)的關係,轉向為從「要更新什麼位置的資料」來思考,故 head & non-head 可以視同同一個方式來處理,省去 if statement 的例外處理狀況。
- [ ] 原本的程式碼 (10 行)
```C
void remove_list_node(List *list, Node *target)
{
Node *prev = NULL;
Node *current = list->head;
// Walk the list
while (current != target) {
prev = current;
current = current->next;
}
// Remove the target by updating the head or the previous node.
if (!prev)
list->head = target->next;
else
prev->next = target->next;
}
```
- [ ] 有「品味」的版本 (4 行)
```C
void remove_list_node(List *list, Node *target)
{
// The "indirect" pointer points to the *address*
// of the thing we'll update.
Node **indirect = &list->head;
// Walk the list, looking for the thing that
// points to the node we want to remove.
while (*indirect != target)
indirect = &(*indirect)->next;
*indirect = target->next;
}
```
* [Applying the Linus Torvalds "Good Taste" Coding Requirement](https://medium.com/@bartobri/applying-the-linus-tarvolds-good-taste-coding-requirement-99749f37684a)
* 演示矩陣初始化,從雙層 for loop -> 單層 for loop + if statement -> 單層 for loop 的過程
> The fewer conditions you test for, the better your code “tastes”.
* [Pointer to pointer 與 Linked List 的解釋](http://blog.udn.com/chungchia/5978902)
### linked list 的用途
* 存取不連續的資料(例如:到分散式系統)
* 作業系統的任務排程(例如 [FreeRTOS 的 Ready List](http://wiki.csie.ncku.edu.tw/embedded/freertos#Ready%20list%20%E7%9A%84%E8%B3%87%E6%96%99%E5%BD%A2%E6%85%8B) ,是讓在Ready State內的所有不同 Tasks 各自對應的 TCBs 串接在一起)
### linked list 的優點
* 刪除 node 只需要常數時間
### C 語言不提供內建 linked list 函式庫的原因
* 寫不出既通用,效能又好,又能直接存取記憶體的通用函式
* 必須靠程式設計師,從工程角度,就實務應用的需求,就彈性與效能取得妥協
### [include/linux/list.h](https://github.com/torvalds/linux/blob/master/include/linux/list.h)
* 一開始不容易看懂,因為充滿了 inline 跟 macro
* 設計上是 circular linked list
* [list_for_each](https://github.com/torvalds/linux/blob/master/include/linux/list.h#L455) 是一個抽象化的 iterate ADT 實做
* list_for_each 內的 pos 如果在操作過程中被刪除,將導致 pos->next 變成 undefined,list_for_each_safe 增加了一個 n 來儲存 pos->next
* 可參考[Stackoverflow上關於 list_for_each_safe 的討論](https://stackoverflow.com/a/9208960/500983)
```C
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
```
### Circular Linked List -- [龜兔賽跑(Floyd's algorithm)](http://www.csie.ntnu.edu.tw/~u91029/Function.html#4)
> 1. 演算法使用兩個指標,烏龜一次走一步、兔子則是走兩步,兩者速度不同,當 linked list 中存在迴圈(循環)時,則兔子總有一天會追上烏龜,並且烏龜與兔子所行走得距離差必定是迴圈長度的倍數。
> 2. 龜一倍速、兔兩倍速,故龜兔的行走距離差,剛好是龜的行進距離。
> 3. 由於龜與兔的行進距離差 = 龜的行進距離,故龜兔的行進距離差 = 循環長度的倍數。

#### [如何找出迴圈起點](https://hackmd.io/MhDrJ_zQR4ma4XaxSrVKtg?view#%E4%BD%BF%E7%94%A8%E6%BC%94%E7%AE%97%E6%B3%95)
利用距離差為整數倍的特性推導即可。
假設兩者在距離起點 $x$ 的點 $P_x$ 相遇,因此點必在迴圈上,可得知 $x$ 為迴圈長度 $\lambda$ 的整數倍,接著令 $b$ 為迴圈起始點 $P_\mu$ 與 $P_x$ 的距離,令 $a$ 為 $P_\mu$ 前的某一點與 $P_\mu$ 的距離,使得 $a+b=\lambda$,其中 $P_\mu$ 與起點的距離為 $\mu$,以此可以推導出:
$x=n\lambda, n\in \mathbb{Z}^{+}$
$\mu = x - b = (n - 1) \lambda + (\lambda - b) = (n-1)\lambda + a$
其中迴圈起始點與起點的距離為: $(n-1)\lambda + a$
而 $x$ 與迴圈起始點的距離為: $\lambda - b = a$
以下示意圖:

演算法:
1. 將烏龜推回起點,兔子不動,接著兩者皆以一次一步的方式前進。
2. 兩者必定會在迴圈起始點 $P_\mu$ 相遇的推論:
* 烏龜從起點移動到迴圈起始點 $P_\mu$ 的距離 $\mu = (n-1)\lambda + a$
* 兔子從 $P_x$ 移動到迴圈起始點 $P_\mu$ 的距離 $= k\lambda + (\lambda - b) = k\lambda + a$
* 只要 $k = n - 1$ ,則兩者必定會在迴圈起始點 $P_\mu$ 一起相遇
#### 取得迴圈長度
讓兔子從迴圈起始點 $P_x$ 繞一圈便可以取得迴圈長度 $\lambda$ 。
### Glib Async Queue
* Async 表示有考慮到多執行緒下的資源保護
### Offsetof Macro
* 透過此 Macro 來實做 [Container_of](https://adrianhuang.blogspot.com/2010/01/linux-kernel-containerof.html) macro
### 提問
:::warning
:::
---
## [你所不知道的 C 語言:技巧篇](https://hackmd.io/s/HyIdoLnjl)
### 重點
*
### 心得
*
### 提問
:::warning
:::
---
## [GNU/Linux 開發工具](https://hackmd.io/c/rJKbX1pFZ)
Git, HackMD, LaTeX 語法 (特別是數學式), GNU make, perf, gnuplot
### Ubuntu Linux 安裝上的一些小調整
* 讓 Ubuntu Linux與 Windows 10 的時間可以同步(不會差8小時):
```
$ timedatectl set-local-rtc 1
```
* [讓 iPhone USB 個人熱點可以在 Ubuntu Linux 上使用](https://askubuntu.com/questions/126340/how-do-i-set-up-the-iphone-usb-ethernet-driver)
* [調整開機選單的預設進入選項](https://askubuntu.com/questions/781157/how-to-change-the-order-to-choose-os-during-boot)
```
$ sudo vim /etc/default/grub
Now change the GRUB_DEFAULT=0 to any entry you wish.
The first entry is 0 , second Entry is 1 and so on.
$ sudo update-grub
```
* 系統環境
```
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 142
Model name: Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
Stepping: 9
CPU MHz: 800.074
CPU max MHz: 3500.0000
CPU min MHz: 400.0000
BogoMIPS: 5808.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 4096K
NUMA node0 CPU(s): 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp flush_l1d
```
### Git
* 閱讀了以下資料
* [Git-it](https://github.com/jlord/git-it-electron) : 熟悉指令操作
```
$ git init
$ git pull origin master
$ git diff
$ git commit -am "commit message"
```
* [Git commit message 撰寫和改進實例](https://hackmd.io/s/HJQk5dt2x)
* 參考了以下資料(未熟讀完)
* [30 天精通 Git 版本控管](https://github.com/doggy8088/Learn-Git-in-30-days)
* [為你自己學 Git -- 高見龍](https://gitbook.tw/)
### Vim
* .vimrc 設定
* 安裝 curl : sudo apt install curl
* 安裝 [Minimalist Vim Plugin Manager](https://github.com/junegunn/vim-plug)
* 使用 [終端機,Vim 設定](https://hackmd.io/DTcTvbGwRtWcKoA1CZmQ3Q?view#vimrc-%E7%AF%84%E4%BE%8B)教學文章內的 .vimrc設定
### HackMD
* [HackMD 的官方教學文件](https://hackmd.io/TKNuhom7S62OV6bDyBglXA)
* Markdown 語法參考了 [Github 上的 Markdown 語法教學課程](https://lab.github.com/githubtraining/communicating-using-markdown)
### LaTeX 語法
* 試了幾個[範例](https://hackmd.io/c/rJKbX1pFZ/https%3A%2F%2Fhackmd.io%2Fs%2FB1RwlM85Z)的數學式
* $N(b,d)=(b-1)M$
* 表達一個 $3 \times 3$ 矩陣:
$\left(
\begin{array}{ccc}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{array}
\right)$
### Makefile
### Perf
### GnuPlot
---
## [附錄:提問的智慧](http://mis.ndhu.edu.tw/docu/question.htm)
### 參考資料
- [最新版英文原文](http://www.catb.org/~esr/faqs/smart-questions.html)
- [對應最新版原文的繁體中文翻譯](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)
### 重點
* 在提問之前
* 在你準備要通過電子郵件、新聞群組或者聊天室提出技術問題前,請先做到以下事情:
1. 嘗試在你準備提問的論壇的舊文章中搜尋答案。
1. 嘗試上網搜尋來找到答案。
1. 嘗試閱讀手冊來找到答案。
1. 嘗試閱讀常見問題文件(FAQ)來找到答案。
1. 嘗試自己檢查或試驗來找到答案
1. 向你身邊的強者朋友打聽來找到答案。
1. 如果你是程式開發者,請嘗試閱讀原始碼來找到答案
* 當你提問時
* 小心選擇你要提問的場合。如果你做了下述的事情,你很可能被忽略掉或者被看作失敗者:
* 在與主題不合的論壇上貼出你的問題
* 在探討進階技術問題的論壇張貼非常初級的問題;反之亦然
* 在太多的不同新聞群組上重複轉貼同樣的問題(cross-post)
* 向既非熟人也沒有義務解決你問題的人發送私人電郵
* stackoverflow
* Stack Exchange 已經成長到[超過一百個網站](http://stackexchange.com/sites),以下是最常用的幾個站:
* Super User 是問一些通用的電腦問題,如果你的問題跟程式碼或是寫程式無關,只是一些網路連線之類的,請到這裡。
* Stack Overflow 是問寫程式有關的問題。
* Server Fault 是問伺服器和網管相關的問題
* 如果英文是你的第一外語(Second language),提示潛在回覆者你有潛在的語言困難是很好的:
> English is not my native language; please excuse typing errors.
* 英文不是我的母語,請原諒我的錯字或文法
> If you speak $LANGUAGE, please email/PM me;
> I may need assistance translating my question.
* 如果你說**某語言**,請寄信/私訊給我;我需要有人協助我翻譯我的問題
> I am familiar with the technical terms,
> but some slang expressions and idioms are difficult for me.
* 我對技術名詞很熟悉,但對於俗語或是特別用法比較不甚了解。
> I've posted my question in $LANGUAGE and English.
> I'll be glad to translate responses, if you only use one or the other.
* 我把我的問題用**某語言**和英文寫出來,如果你只用一種語言回答,我會樂意將其翻譯成另一種。
### 心得
* 這篇文章整理了在網路上找尋解答,提出問題的方式,與正確與其他網友合作的心態
* 目前在工作上遇到的問題,通常透過Google/Stackoverflow/Quora都可以找到解答,再不行可以詢問資深同事跟Chip FAE技術支援,還沒有真的在論壇上問過問題...
---