指標與陣列的關係是C語言最核心也最易混淆的主題。本文從記憶體模型出發,系統闡述指標與陣列的異同、指標運算機制、函數參數傳遞、動態記憶體管理、多維陣列佈局等進階主題,助你建立精確的心智模型。
陣列:連續儲存同質元素的固定大小記憶體區塊,陣列名稱在大多數表達式中退化為指向首元素的指標,但本質不同:
sizeof(array) 回傳整個陣列位元組大小&array 型別為 int (*)[N](陣列指標),而非 int*指標:儲存記憶體位址的變數,支援算術運算、間接存取、動態分配。
int vector[5] = {1,2,3,4,5};
int *pv = vector; // 等價於 &vector[0],型別 int*
int (*pa)[5] = &vector; // 型別 int (*)[5],指向整個陣列
printf("%zu\n", sizeof(vector)); // 20 (5*4)
printf("%zu\n", sizeof(pv)); // 8 (64位系統指標大小)
printf("%zu\n", sizeof(pa)); // 8
printf("%p %p\n", (void*)vector, (void*)&vector); // 數值相同,型別不同
pv[i] 編譯器自動轉換為 *(pv + i),指標運算以元素大小為單位:
int *p = vector;
printf("%d\n", *(p+1)); // 2,相當於 p[1]
printf("%d\n", *(vector+1)); // 2,陣列名退化為指標
// 關鍵差異:指標可修改,陣列名不可
p++; // 合法
vector++; // 編譯錯誤:左值要求
char* getLine(void) {
const size_t INCREMENT = 10;
char *buffer = malloc(INCREMENT);
char *pos = buffer;
size_t maxlen = INCREMENT, len = 0;
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
if (++len >= maxlen) {
maxlen += INCREMENT;
char *newbuf = realloc(buffer, maxlen);
if (!newbuf) { free(buffer); return NULL; }
pos = newbuf + (pos - buffer); // 維持相對位移
buffer = newbuf;
}
*pos++ = ch;
}
*pos = '\0';
return buffer; // 呼叫者負責 free()
}
void process(int n) {
int vla[n]; // 僅限區塊作用域,生命週期隨函數結束
// ...
}
// 以下三種宣告等價
void func(int arr[]);
void func(int arr[10]); // 大小被忽略
void func(int *arr); // 本質:傳遞首元素位址
// 必須額外傳遞長度
void print_array(int *arr, size_t len) { ... }
// 字串慣例:以 '\0' 結尾,無需傳長度
void print_str(const char *str) { ... }
int *ptr_array[3]; // 指標陣列:3個 int* 元素
int (*arr_ptr)[3]; // 陣列指標:指向含3個int的陣列
int matrix[2][3]; // 二維陣列:連續儲存 2*3 個 int
// 二維陣列記憶體佈局:行優先
int matrix[2][3] = {{1,2,3},{4,5,6}};
// 記憶體:1 2 3 4 5 6
// &matrix[0] = 0x1000, &matrix[1] = 0x100C (差12 bytes = 3*sizeof(int))
// 必須指定除第一維外的所有維度 void print_2d(int arr[][3], int rows); // OK void print_2d(int (*arr)[3], int rows); // 等價寫法 // 三維陣列 void print_3d(int (*arr)[2][4], int depth); // arr[depth][2][4]
int rows = 3, cols = 5; int *matrix = malloc(rows * cols * sizeof(int)); matrix[i * cols + j] = value; // 手動計算位移
int **matrix = malloc(rows * sizeof(int*));
matrix[0] = malloc(rows * cols * sizeof(int));
for (int i = 1; i < rows; i++) {
matrix[i] = matrix[0] + i * cols; // 設定各行起始位址
}
// 使用 matrix[i][j] 自然語法存取
// 複合字面量初始化 (C99)
int *jagged[3] = {
(int[]){100},
(int[]){10, 20, 30},
(int[]){1, 2, 3, 4, 5}
};
// 每行長度不同,存取需額外維護長度資訊
valgrind --leak-check=full ./program深入理解指標與陣列的記憶體語義,是寫出高效、安全 C 程式的關鍵。建議配合圖解記憶體佈局、GDB 觀察執行時狀態、閱讀開源專案原始碼,逐步建立直覺性掌握。