# 2018q3 Homework 1 材料閱讀筆記 contributed by <`KittyLiou`> :::danger 你的提問呢?回顧你過去開發的程式,難道沒想到概念上有衝突或者激發出更多想法嗎? :notes: jserv ::: :::info 報告 jserv,我有再補新的提問了 -- KittyLiou ::: --- 本篇筆記主要用於記錄閱讀以下教材後的重點整理和心得 - [x] [為什麼要深入學習 C 語言?](https://hackmd.io/s/HJpiYaZfl) - [ ] [你所不知道的 C 語言: 指標篇](https://hackmd.io/s/HyBPr9WGl#) - [ ] [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/s/SJ6hRj-zg) - [ ] [你所不知道的 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) - [ ] [你所不知道的 C 語言:技巧篇](https://hackmd.io/s/HyIdoLnjl) - [ ] [GNU/Linux 開發工具](https://hackmd.io/c/rJKbX1pFZ) --- ## 為什麼要深入學習 C 語言? * 對應材料連結: [為什麼要深入學習 C 語言?](https://hackmd.io/s/HJpiYaZfl) ### 重點整理 * 授權條款種類: 1. GPL: 任何使用/修改/衍生的GPL類庫都須開源且「免費」(對有代碼機密問題的商業軟體較不友善) 2. LGPL: 類似GPL,若只是「動態連結」的話使用上是自由的(可用於商業軟體) 3. BSD: 允許代碼再修改及發佈(開源或專有皆可),具「傳染性」 4. MIT: 限制最鬆,只要不把作者名字塗掉即可做任何事 延伸閱讀: [五種開源授權規範的比較 (BSD, Apache, GPL, LGPL, MIT)](http://inspiregate.com/internet/trends/74-comparison-of-five-kinds-of-standard-open-source-license-bsd-apache-gpl-lgpl-mit.html) * 為什麼不探討 C++? 1. C++ 改版太快 2. C99 後 C 和 C++ 其實已經分道揚鑣 * C語言之父 -- [Dennis Ritchie](https://zh.wikipedia.org/wiki/%E4%B8%B9%E5%B0%BC%E6%96%AF%C2%B7%E9%87%8C%E5%A5%87) * 創造 C 語言 * 參與 Unix 開發 * 和[Brian Kernighan](https://zh.wikipedia.org/wiki/%E5%B8%83%E8%90%8A%E6%81%A9%C2%B7%E6%9F%AF%E6%9E%97%E6%BC%A2)共同撰寫了「[The C Programming Language](https://zh.wikipedia.org/wiki/C%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80_(%E4%B9%A6))」(K&R C) * Plan9 - 貝爾實驗室將之當為 Unix 的後繼者 - Everything is a file. * 第一個 C 語言編譯器是怎麼編寫的? * compiler bootstrapping * 先為 C 最簡單的子集( C0 )寫一個 compiler,因為 C0 很簡單,compiler 可以直接用組合語言寫;再用 C0 寫 C1 ( C 的子集,較 C0 複雜 )的 compiler,以此類推下去 * 參考資料: http://blog.jobbole.com/94311/ * ISO/IEC 646 * ISO 和 IEC 分別代表「國際標準化組織」和「國際電工委員會」兩個不同的組織 * 標準化 Character Set * ISO/IEC 9899 * 最終版其實是要錢的 * 為什麼1998的東西2007才發表? 因為有經過一些微調( ex:商標 or 文法錯誤等 ) * object (in C) * region of data storage in the execution environment, the contents of which can represent values * 只要有佔用空間,就是 object * &念法 bit-wise operation: and used as pointer: address of <比較> * 念做 value of * lvalue 的 L 是「locator」 * 參考資料: [Understanding lvalues and rvalues in C and C++](https://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c) * pointer to array Code: ```clike #include <stdio.h> int main() { char arr[10] = "Hello"; printf("%x\n", arr); printf("%x %x\n", arr+1, &arr+1); return 0; } ``` Output: ``` 22fe46 22fe47 22fe50 ``` 參考資料: [How come an array's address is equal to its value in C?](https://stackoverflow.com/questions/2528318/how-come-an-arrays-address-is-equal-to-its-value-in-c) * GDB * 可進行單步執行、改變程式執行順序( 透過 set $pc )、中斷在特定的地址 * 支援多種語言( ex:C, C++, Objective-C, Ada, Pascal, ... ) * 可模擬 CPU instruction的執行(instruction simulator),不過無法模擬周邊設備 * 編譯時記得加-g,格式: DWARF(一種 debugging data format) * whatis 可印出 type ``` (gdb) whatis b[0] type = struct {...} ``` * wchar (wide character) * 長度大於一個 byte * L"hi there\n" : wide 版本的 string literal * Record and Replay * record 可以記下程式整個執行的過程,replay 可以回到 crash 前的狀態 * 若 GDB 夠新,還可以再往前回推更之前的狀態,並可以知道當下 stack 的狀況或是執行緒的狀況,改變之前狀態並繼續執行 ### 心得 * 在看完直播錄影後,真心的感受到自己對 C 的了解實在太不透徹了,大一的時候也曾經很認真的翻課本,以為自己對 C 有一定的掌握度了,殊不知會的根本只能算是皮毛,尤其是 pointer to array 那個部分,以下圖為例: ![](https://i.imgur.com/rHAdzjF.png) 我思考了很久到底為什麼array前面加上&出來的位置竟然會一樣,我對 array 一直將之理解成等同於指向第0個 element 的 pointer,因此看到 &arr 時我變很理所當然的認為它應該是一個 pointer to pointer,因此認為 arr 和 &arr 兩者的記憶體位置應該不同,然而實際上它們的位置竟然一樣,雖然位置一樣但代表的意義卻大不相同,兩者各自+1後前者只加了一個 char 的長度,後者卻加了10個 char 的長度,可見其型別的不同,一個是 pointer to char,另一個是 pointer to char[10],因此同樣是加1,它們所代表的一個單位卻不一樣,這是我當初大一在學 C 語言時所沒有注意到的。 * 此外,透過這次的影片,我學到了很多之前沒接觸或沒想過的議題,像是 C 是如何用 C 開發可以編譯自己的 compiler,還有對於不同的授權條款我現在終於有了基礎的認知,真的就如 Jserv 所講的,閱讀這些材料確實要花上不少時間,因為常常碰到一個自己沒想過的議題就要暫停影片自己再多搜尋一些相關的知識,但每看完一個影片也紮紮實實地感受到自己又進步了一點,雖然目前還沒把全部的影片看完,但之後一定會一一補上的。 ### 題問 * 想請問規格書的建議使用方式?應該將其當作工具書就好,遇到問題時再翻閱,還是當成像是教科書一樣整本研讀呢? :::info 當然是視同工具,就像辭典一樣,但你需要勤勞翻閱。將心比心,如果 Google 和 Apple 都跟你一樣似懂非懂,他們開發出來的手機,你敢用嗎? :notes: jserv ::: --- ## 你所不知道的 C 語言: 指標篇 * 對應材料連結: [你所不知道的 C 語言: 指標篇](https://hackmd.io/s/HyBPr9WGl#) ### 重點整理 * [godbolt](http://gcc.godbolt.org/): 直接在網頁上看到 gcc 生成的程式碼,可套用不同的編譯器及硬體架構 ![](https://i.imgur.com/n6EeCKG.png) * function pointer * 參考資料: [Function Pointer in C](https://www.geeksforgeeks.org/function-pointer-in-c/) * `(*(void(*)())0)();` 解析: 其中`void(*)()`的部分為一個function pointer,因此上述程式碼等於將 0 強制 cast 成 function pointer 並執行,相當於呼叫地址為 0 的函式 * `void ( *signal(int sig, void (*handler)(int)) ) (int);` 解析: ([來源](https://stackoverflow.com/questions/15739500/how-to-read-this-prototype)) ```clike signal -- signal signal( ) -- is a function signal( sig ) -- with a parameter named sig signal(int sig, ) -- of type int signal(int sig, handler ) -- and a parameter named handler signal(int sig, *handler ) -- which is a pointer signal(int sig, (*handler)( )) ) -- to a function signal(int sig, (*handler)(int)) ) -- taking an int parameter signal(int sig, void (*handler)(int)) ) -- and returning void *signal(int sig, void (*handler)(int)) ) -- returning a pointer ( *signal(int sig, void (*handler)(int)) )( ) -- to a function ( *signal(int sig, void (*handler)(int)) )(int) -- taking an int parameter void ( *signal(int sig, void (*handler)(int)) )(int); -- and returning void ``` * C 語言的目的 * 為了開發 Unix 作業系統 ( C 語言所代表的文化就是 Unix ) * 充分掌握硬體 * incomplete type * 沒有明確大小(不是一個 object),不可create instance * 但可以創造 pointer to incomplete type * 下列 code 都是合法的 ```clike #include <stdio.h> struct A; int main() { return 0; } ``` ```clike #include <stdio.h> struct A; int main() { struct A *a; return 0; } ``` * 下列 code 卻是不合法的 ```clike #include <stdio.h> struct A; int main() { struct A a; return 0; } ``` 錯誤訊息: ![](https://i.imgur.com/vBze0RL.png) * const 參考資料: [const 放置位置的意義](http://blog.xuite.net/tsai.oktomy/program/65131235-const+%E6%94%BE%E7%BD%AE%E4%BD%8D%E7%BD%AE%E7%9A%84%E6%84%8F%E7%BE%A9) ```clike const char *pContent; //指標指向的內容為常量不可變 char * const pContent; //指標本身為常量不可變 char const *pContent; //指標指向的內容為常量不可變 ``` * cdecl * 可以將英文轉成 code * 或是 code 轉成英文 * A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. * 關鍵描述!規範 `void *` 和 `char *` 彼此可互換的表示法 * 但 char * 可以 dereference,void * 不行 * pointer to pointer * 什麼時候會用到? drop the head of a linked list * Pointers vs. Arrays ```clike= int main() { int x[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("%d %d %d %d\n", x[4], *(x + 4), *(4 + x), 4[x]); } ``` 輸出: ```4 4 4 4``` C99 規格書[6.5.2.1] Array subscripting > 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). * extern * extern 是給 linker 看的 * extern 可以聲明變數會在其他的位置被定義,這個位置可能是在同一份文件之中,或是在其他文件之中 * 參考資料: [變數、函式可視範圍(static 與 extern)](https://openhome.cc/Gossip/CGossip/Scope.html) * int *a v.s int\* a int *a 相對於 int* a 是個比較好的寫法,以下列 code 為例: ```clike int *a, b; //a is a pointer to int, and b is an int ``` 若寫成 `int* a, b`,雖然意義上是一樣的,但看起來 `int*` 像是一種 type,就容易誤以為 b 也是一個 pointer to int,因此寫做 `int *a` 是一個較佳的寫法 * LP64 data model 基本上它寫什麼就代表什麼會是 64 bits 像是 LP64 就代表 long 和 pointer 會是 64 bits * argc argv * 由 shell command interpreter 提供 ### 心得 ### 提問 1. 以下 code 取自 [你所不知道的 C 語言 : 指標篇 #Pointers vs. Arrays](https://hackmd.io/s/HyBPr9WGl#Pointers-vs-Arrays) 由於我以前寫的時候通常都是寫做`int argc, char *argv[]`,因此針對以下 code 我有兩個疑問: (1) 為什麼`char (*argv)[0]`中的`(*argv)`要加括號? (2) 為什麼要寫做`char (*argv)[0]`而不只寫做`char (*argv)[]`? ```clike= #include <stdio.h> int main(int argc, char (*argv)[0]) { puts(((char **) argv)[0]); return 0; } ``` --- ## 你所不知道的 C 語言: 函式呼叫篇 * 對應材料連結: [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/s/SJ6hRj-zg) ### 重點整理 ### 心得 ### 提問 --- ## 你所不知道的 C 語言: 遞迴呼叫篇 * 對應材料連結: [你所不知道的 C 語言: 遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl) ### 重點整理 ### 心得 ### 提問 --- ## 你所不知道的 C 語言: 前置處理器應用篇 * 對應材料連結: [你所不知道的 C 語言: 前置處理器應用篇](https://hackmd.io/s/S1maxCXMl) ### 重點整理 ### 心得 ### 提問 --- ## 你所不知道的 C 語言: goto 和流程控制 * 對應材料連結: [你所不知道的 C 語言: goto 和流程控制](https://hackmd.io/s/B1e2AUZeM) ### 重點整理 ### 心得 ### 提問 --- ## 你所不知道的 C 語言: linked list 和非連續記憶體操作 * 對應材料連結: [你所不知道的 C 語言: linked list 和非連續記憶體操作](https://hackmd.io/s/SkE33UTHf) ### 重點整理 ### 心得 ### 提問 --- ## 你所不知道的 C 語言:技巧篇 * 對應材料連結: [你所不知道的 C 語言:技巧篇](https://hackmd.io/s/HyIdoLnjl) ### 重點整理 ### 心得 ### 提問 --- ## GNU/Linux 開發工具 * 對應材料連結: [GNU/Linux 開發工具](https://hackmd.io/c/rJKbX1pFZ) ### 重點整理 ### 心得 ### 提問