# 指標篇
## 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 提供操作多維陣列的機制,但實際上在記憶體的呈現只有一維
> [未完]