# 2018q3 Homework4 (assessment)
contributed by <`AlecJY`>
## [第 4 週測驗題(中)](https://hackmd.io/s/Syl6me49Q)
## [第 4 週測驗題(下)](https://hackmd.io/s/By7Lwz4qm)
### `ptr.c`
``` C=
int main() {
int *ptr = 0;
return *ptr;
}
```
這段程式碼在執行時期會產生 segmentation fault 。 這段程式碼在第二行定義了一個 int 指標 `ptr` 並且賦值為 0 ,在第三行回傳 `*ptr` ,也就是將位址為 0 的指標 dereference 後回傳,由於位址 0 是一個無效的位址,所以會產生 segmentation fault。
### `ptr1.c`
``` C
int main() { return *((int *) 0); }
```
這段程式碼在執行時期會產生 segmentation fault 。 這邊對記憶體位址為 0 的指標做 dereference 。 由於位址 0 是一個無效的位址,所以會產生 segmentation fault。
### `ptr2.c`
``` C
int main() { return &*((int *) 0); }
```
這段程式碼跟上一段程式碼比起來只差在多了一個 `&` ,翻閱 C99 規格第 79 頁的註腳中有一段描述是
> &*E is equivalent to E (even if E is a null pointer)
所以這段程式碼只是單純的回傳 0 而已,可以正常的執行
另外如果使用 GCC 編譯的時候會產生如下的錯誤訊息
```
warning: return makes integer from pointer without a cast
```
因為 `main` 要求回傳 `int` ,實際上回傳的是 `int *` ,所以如果在前面再加一個 `(int)` 強制轉型為 `int` 就可以消除這個警告
## `ptr3.c`
``` C
#include <stddef.h>
int main() { return &*NULL; }
```
這段程式碼跟前一段的差別在於 `((int *) 0)` 改成了 NULL ,根據 C99 規格章節 7.17 第 254 頁
> **NULL**
> which expands to an implementation-defined null pointer constant
再根據章節 6.3.2.3 第 47 頁對於 null pointer 的描述
> An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
所以這段程式碼一樣是回傳 0 ,執行上不會有問題。
### `ptr4.c`
``` C
#include <stddef.h>
int main() {
return &*(*main - (ptrdiff_t) **main);
}
```
參考 [你所不知道的C語言:指標篇](https://hackmd.io/s/HyBPr9WGl) 裡面的解釋
> 程式碼 (********puts) 可看作 (*(*(*(*(*(*(*(*puts)))))))),最裡面的括號 (*puts) 由 [ 6.5.3.2-4 ] 可知它是一個 function designator。再根據 [ 6.3.2.1 ],它最後會被轉為 pointer to function returning type。往外延伸一個括號 (*(*puts)) 由於最裡面的括號是一個 function designator,再多一個 * operator 它還是一個 function designator,最後也會被轉為 pointer to function returning type,依此類推最後 (********puts) 仍會是一個 function designator。
`**main` 是一個 function designator ,之後將他強制轉型成 `ptrdiff_t` ,這是一個代表指標和指標相減後得到的值的型別,將 `*main` 這個 function designator 和 `(ptrdiff_t) **main` 相減後會得到 0 ,所以問題就化簡為跟 `ptr2.c` 差不多的問題, `&*` 可以消去,因此實際上回傳的值是 0 ,執行上不會有問題。