| 特性 | 靜態陣列 | 動態陣列 |
| 大小決定 | 編譯期常數 | 執行期變數 |
| 儲存區 | 棧(區域)或資料段(全域) | 堆(malloc/new) |
| 大小可變 | 不可 | 可(realloc) |
| 釋放責任 | 自動 | 程式設計師手動 free |
基本實作步驟
- 宣告指標:
int* arr = nullptr;
- 讀取長度:
int n; scanf("%d", &n);
- 配置記憶體:
arr = (int*)malloc(n * sizeof(int));
- 檢查失敗:
if (!arr) { perror("malloc"); exit(1); }
- 使用陣列:
arr[i] = ... 或 *(arr+i)
- 釋放記憶體:
free(arr); arr = nullptr;
完整範例:字元動態陣列
#include <stdio.h>
#include <stdlib.h>
int main() {
int len;
printf("請輸入陣列長度:");
if (scanf("%d", &len) != 1 || len <= 0) return 1;
char* arr = (char*)malloc(len * sizeof(char));
if (!arr) {
fprintf(stderr, "記憶體配置失敗\n");
return 1;
}
printf("請輸入 %d 個字元:", len);
for (int i = 0; i < len; ++i) {
scanf(" %c", &arr[i]); // 空白跳過換行
}
printf("陣列內容:");
for (int i = 0; i < len; ++i) {
putchar(arr[i]);
putchar(' ');
}
putchar('\n');
free(arr);
return 0;
}
進階:動態擴容(模擬 vector)
typedef struct {
int* data;
size_t size; // 當前元素數
size_t capacity; // 已配置容量
} DynArray;
void init(DynArray* a) {
a->data = nullptr; a->size = a->capacity = 0;
}
void push_back(DynArray* a, int val) {
if (a->size == a->capacity) {
size_t newCap = a->capacity ? a->capacity * 2 : 4;
int* tmp = (int*)realloc(a->data, newCap * sizeof(int));
if (!tmp) { perror("realloc"); exit(1); }
a->data = tmp; a->capacity = newCap;
}
a->data[a->size++] = val;
}
void freeArray(DynArray* a) { free(a->data); init(a); }
常見錯誤與避坑
| 錯誤 | 後果 | 修正 |
malloc(len) 忘乘 sizeof(type) | 配置過小,寫入越界 | 永遠 n * sizeof(T) |
未檢查 malloc 回傳值 | 解參考空指標,崩潰 | if (!ptr) handle_error(); |
free 後未置 nullptr | 懸空指標,二次釋放/誤用 | free(p); p = nullptr; |
realloc 直接賦值給原指標 | 失敗時原指標遺失,記憶體洩漏 | 用暫存變數接收,檢查後再賦值 |
| 釋放非堆記憶體(棧陣列、字串常數) | 未定義行為 | 僅釋放 malloc/calloc/realloc 回傳的指標 |
總結
- 動態陣列 =
malloc 配置 + 指標存取 + free 釋放。
- 核心優勢:執行期決定大小、可擴容、生命週期可控。
- 現代 C++ 應優先使用
std::vector,C 語言專案才手寫動態陣列結構。
- 上一篇文章: No
- 下一篇文章: C 語言實作「三天打魚兩天曬網」判斷邏輯
Copyright ©
程式碼之家 All Rights Reserved