# 指標篇 ## typedef - 範例 - 建立 PFI 作為一個指向「一個擁有兩個 char * 當作參數並回傳 int 的函式」的指標的別名 ```c typedef int (*PFI)(char *, char *); ``` - 未使用 typedef ```c int do_math(float arg1, int arg2) { return arg2; } int call_a_func(int (*call_this)(float, int)) { int output = call_this(5.5, 7); return output; } int final_result = call_a_func(&do_math); ``` - 改寫: ```c typedef int (*MathFunc)(float, int); int do_math(float arg1, int arg2) { return arg2; } int call_a_func(MathFunc call_this) { int output = call_this(5.5, 7); return output; } int final_result = call_a_func(&do_math); ``` [Wikipedia: typedef](https://zh.wikipedia.org/wiki/Typedef) :::info 除了閱讀 Wikipedia,請務必詳閱 C99/C11 規格書描述 :notes: jserv ::: - 呼叫地址為 0 的函式(? ```c int main() { typedef void (*funcptr)(); (* (funcptr) (void *) 0)(); } ``` - 0 這個地址在使用者層級不能隨意呼叫,所以會發生 segmentation fault 記憶體存取的錯誤 :::info 這限制來自 [MMU](https://en.wikipedia.org/wiki/Memory_management_unit),請思考在 GNU/Linux 上對應的處理機制為何 :notes: jserv ::: * 回傳 function pointer 的 function ```c void ( *signal(int sig, void (*handler)(int)) ) (int); ``` (https://stackoverflow.com/questions/15739500/how-to-read-this-prototype) * Q:signal 的用途? * C99 [7.14.1.1] The signal function * The signal function chooses one of three ways in which receipt of the signal number sig is to be subsequently handled. ## 一些名詞 - C99 [3.14] object - region of data storage in the execution environment, the contents of which can represent values - 有明確的大小 (cf. incomplete type) - 資料:連續的記憶體 - undefined behavior - e.g. i++++++ 丟到 compiler => ? 怎樣是對怎樣是錯 :::info 可參照 [未定義行為篇](https://hackmd.io/s/Skr9vGiQm) :notes: jserv ::: - C99 [6.2.5] imcomplete type - An array type of unknown size is an incomplete type. ## pointer type - 可能衍生自 function / object / incomplete type -- 稱作 referenced type - C99 [6.2.5] - The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. - C99 [6.2.5] ## 問題 :::warning :question: > 這是 C 語言只有 call-by-value 的實證,函式的傳遞都涉及到數值 why?? ::: ## 指標的指標 ```C=1 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; } ``` ``` 1 ``` 沒改到 A 的值,因為傳給 func 的參數是副本,lifetime 只在函式裡({ p = &B; }),ptrA 內含值其實是沒更動到的 ```clike=1 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; } ``` ``` 2 ``` 代入的 p 的 lifetime 是整個 main block ## Pointers vs. Arrays - x[4], *(x + 4), *(4 + x), 4[x] 都是指到同一個位址 - C 沒有真正的陣列/矩陣 - C 提供操作多維陣列的機制,但實際上在記憶體的呈現只有一維 > [未完]