| 層面 | 陣列 int a[10] | 指標 int *p |
|---|---|---|
| 記憶體區域 | 棧 (靜態/自動儲存期) | 堆 (malloc) 或任意位址 |
| 名稱本質 | **常量指標** (首元素位址,不可修改) | **變量指標** (可指向任意位址) |
| sizeof | 整個陣列大小 (40 位元組) | 指標大小 (4/8 位元組) |
| 賦值 | 不可整體賦值 | 可任意賦值 |
**核心口訣**:陣列名在表達式中 (除 sizeof、&、字串字面常數初始化外) 自動轉換為指向首元素的指標。
int a[5] = {1,2,3,4,5};
int *pa[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]}; // 指標陣列,每元素存 int*
// 存取:a[i] vs *pa[i]
int *pv = (int *)malloc(5 * sizeof(int));
for (int i=0; i<5; ++i) pv[i] = i+1; // pv[i] ≡ *(pv+i)
free(pv);
int *arr[5];
for (int i=0; i<5; ++i) {
arr[i] = (int *)malloc(sizeof(int));
*arr[i] = i;
}
// 或
for (int i=0; i<5; ++i) {
*(arr+i) = (int *)malloc(sizeof(int));
**(arr+i) = i; // 解引用兩次
}
分析:arr+i 是第 i 個指標的位址,*(arr+i) 取得該指標值 (指向 int 的位址),**(arr+i) 解引用到 int 本身。
void init(int *arr, int rows, int cols) { // 實為 int (*arr)[cols]
for (int i=0; i<rows; ++i)
for (int j=0; j<cols; ++j)
*(arr + i*cols + j) = ++num; // 手動線性化索引
}
int a[5][6];
init(&a[0][0], 5, 6); // 必須傳首元素位址
形參 int *arr 僅保留一維資訊,故函數內**無法**用 arr[i][j] 語法,必須手動計算偏移。
int rows = 5, cols = 6;
int *flat = (int *)malloc(rows * cols * sizeof(int)); // 一塊連續區
// 存取:flat[i*cols + j]
free(flat);
int **mat = (int **)malloc(rows * sizeof(int *));
for (int i=0; i<rows; ++i)
mat[i] = (int *)malloc(cols * sizeof(int));
// 存取:mat[i][j] ✓
// 釋放:
for (int i=0; i<rows; ++i) free(mat[i]);
free(mat);
此結構與 char **argv 同構,適合行長度不一的場景 (如文字行)。
int *num1[3];
int num2[3] = {1,2,3};
for (int i=0; i<3; ++i) num1[i] = &num2[i];
for (int i=0; i<3; ++i) printf("%4d", *num1[i]);
void arr_init(int *arr, int rows, int cols) {
int val = 1;
for (int i=0; i<rows; ++i)
for (int j=0; j<cols; ++j)
*(arr + i*cols + j) = val++;
}
void arr_print(int *arr, int rows, int cols) {
for (int i=0; i<rows; ++i) {
for (int j=0; j<cols; ++j)
printf("%4d", *(arr + i*cols + j));
putchar('\n');
}
}
int main() {
int a[5][6], b[7][8];
arr_init(&a[0][0], 5, 6); arr_print(&a[0][0], 5, 6);
arr_init(&b[0][0], 7, 8); arr_print(&b[0][0], 7, 8);
}
void f(int a[][COLS]) 或 void f(int (*a)[COLS]),COLS 必須為常量。char *strs[] 本質同 int **,操作邏輯完全一致。指標與陣列的關係是 C 語言最微妙也最核心的主題。**記住「陣列名在絕大多數場合轉換為指標」,並搞清記憶體佈局 (連續 vs 分散)、生命週期 (棧 vs 堆)、型別資訊保留程度 (一維全失 vs 二維保留次維)**,即可駕馭各種複雜資料結構。