指標與記憶體

互動實驗室 · hybrid JSCPP 載入中…
每節三段:規格程式碼+逐步記憶體圖試跑。瀏覽器試跑用 JSCPP,只跑 stack 範疇的乖片段; 動態配置(malloc)與危險操作(懸空、use-after-free、double-free、洩漏)JSCPP 不支援、也不該在這裡跑, 請到 本地練習/./run.sh 開 sanitizer 跑:未定義行為在這裡「剛好沒崩」會教歪。
experiment 01

指標基本:取址 & 解參考

宣告 int *p = &x; 後,*px 是同一格;透過 *p 寫值就是改 x。預測 printf("%d %d", x, *p)

01_pointer_basics.c
// 透過指標改值
int x = 10;
int *p = &x;   // p 指向 x
*p = 20;        // 改的是 x 本人
printf("%d %d\n", x, *p);
先用記憶體圖預測,再跑對答案

  
experiment 02

傳位址:為什麼 swap 要 &

C 是傳值,函式拿到複本。要改呼叫端的變數,把位址傳進去,函式內用 * 寫回。看記憶體圖追 a、b 指向誰。

02_swap.c
void swap(int *a, int *b){
    int t = *a; *a = *b; *b = t;
}
// 呼叫:
int x = 3, y = 5;
swap(&x, &y);   // x=5, y=3
改成傳值 (int a,int b) 看看會怎樣

  
experiment 03

指標算術與陣列

a[i] 等同 *(a+i)p+nsizeof(*p) 為單位移動。改下面的 i 預測 *(p+i)

a[i] 與 *(p+i) 應永遠相等

  
experiment 04

動態配置:malloc / free

大小到執行期才知道、或要活過函式,就向 heap 要:malloc → 檢查 NULL → 用 → free → 設 NULL。看記憶體圖:指標在 stack、資料在 heap、free 後那塊歸還。

JSCPP 不支援 malloc(stack-only)。動態配置的完整可跑版在 本地練習/03_dynamic_array.c./run.sh 03_dynamic_array.c
experiment 05

危險區:這些只在本地跑

未定義行為 — 一律本地 clang + sanitizer

這些在瀏覽器「剛好沒崩」會給錯誤的安全感。到 本地練習/./run.sh 檔名.c(已開 -fsanitize=address,undefined),錯誤才穩定現形。

懸空指標:回傳區域變數位址,函式返回後失效。./run.sh 04_dangling_return.c → stack-use-after-return
use-after-freefree 後再解參考。./run.sh 05_use_after_free.c → heap-use-after-free
double free:同一塊 free 兩次。./run.sh 06_double_free.c → double-free
記憶體洩漏:忘了 freemac 上 sanitizer 抓不到,需 Instruments;見 README