static 變數。malloc/new),程式設計師手動釋放 (free/delete)。靈活、空間大,但易產生碎片、洩漏、野指標。| 錯誤類型 | 原因 | 防範鐵律 |
|---|---|---|
| 使用未成功分配的記憶體 | 未檢查 malloc/new 回傳值 | 【規則1】使用前必檢查指標是否為 NULL |
| 使用未初始化記憶體 | 誤以為預設為 0;無初始化習慣 | 【規則2】無論何種方式建立陣列/動態記憶體,必賦初值 |
| 越界存取 | 陣列下標「多 1」或「少 1」;迴圈邊界錯誤 | 【規則3】嚴防下標越界,特別注意邊界條件 |
| 記憶體洩漏 | 申請釋放不配對;流程跳過釋放語句 | 【規則4】malloc 與 free 次數必相同,RAII 思想 |
| 釋放後繼續使用 (野指標) | 物件生命週期混淆;回傳堆疊位址;free 後未置 NULL | 【規則5】free/delete 後立即將指標設為 NULL |
兩者語法上可互換(如 a[i] ≡ *(a+i)),但本質天差地別。
char a[] = "hello"; // 陣列在堆疊/靜態區,內容可改
a[0] = 'X'; // OK
char *p = "world"; // p 指向「常數字串區」(唯讀)
p[0] = 'X'; // 編譯通過,執行期崩潰!試圖修改唯讀記憶體
// 陣列:不能直接賦值/比較,需用庫函式
char a[] = "hello", b[10];
strcpy(b, a); // 複製內容
if (strcmp(b, a) == 0) // 比較內容
// 指標:需先分配空間再複製
int len = strlen(a);
char *p = (char*)malloc(len + 1);
strcpy(p, a); // 複製內容,不可 p = a (那只是複製位址)
if (strcmp(p, a) == 0) // 比較內容,不可 p == a (那比較位址)
char a[] = "hello world"; // sizeof(a) = 12 (含結束符 \0)
char *p = a;
sizeof(p); // = 4/8 (指標變數大小),無法得知指向記憶體大小
陣列退化:陣列作為函式參數傳遞時,退化為同類型指標,sizeof 失效。
void Func(char a[100]) { sizeof(a); // 返回 4 或 8,而非 100 }
陣列是「固定地址、固定容量、內容可變」的記憶體塊;指標是「可變地址、指向任意記憶體」的間接工具。指標更靈活但更危險。嚴守五大鐵律,理解退化機制,是寫出健壯 C 程式的基石。