陣列元素 arr[i][j]、結構體成員 st.m 皆可表示為 基址 + 常量偏移 + 變量偏移。UCC 在中間代碼層統一處理。
t 承載地址運算結果。Offset(addr, voff, coff) 產生地址運算中間碼:t1 = &arr; // 取基址 t2 = i * 4; // 變量偏移 t3 = t1 + t2 + 8; // 基址 + 變量偏移 + 常量偏移 *t3 = 30; // 間接賦值
Offsetbase:基址符號(陣列名、結構體變數、指標)。voff:變量偏移符號(如 i*4),無則 NULL。coff:常量偏移位元組數(如結構體成員偏移、陣列固定索引)。Deref 產生間接尋址節點。CreateOffset:建立偏移符號節點基址+常量偏移 創建新符號(型別 SK_Offset),記錄基址符號指標與偏移值。arr[8] 形式,便於除錯。st.arr[2]),遞迴合併偏移(st 偏移 4 + arr[2] 偏移 8 = 12)。(*ptr)[2] 錯誤降級為 ptr[8],必須保留間接層級。Deref 與 AddressOfDeref(t):產生 t2 = *t1,返回新臨時變數;若 t1 來自 &arr,簡化為直接訪問 arr。AddressOf(t):&*t 簡化為 t;對左值生成取址指令並標記 addressed=1,使相關公共子運算式失效(規避別名分析)。| 語境 | 表達式類型 | 說明 |
|---|---|---|
sizeof(arr) | int[4] | 完整陣列類型 |
arr + 1 | int* | 退化為首元素指標 |
&arr + 1 | int(*)[4] | 陣列指標類型 |
C 編譯器根據上下文自動退化,源於早期效率考量(函數傳遞陣列避免複製)。現代建議:明確使用指標參數 int *p 或 int (*p)[N] 表達意圖。