int a[10]; // 10 個 int,連續記憶體,共 40 bytes (假設 int=4)
int *pa = a; // pa 指向 a[0],等價於 &a[0]
int *pb = &a[0]; // 明確取首元素位址
位址 (假設 a 從 0x1000 開始,int=4 bytes): a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 0x1000 0x1004 0x1008 0x100C 0x1010 0x1014 0x1018 0x101C 0x1020 0x1024 | | | | | | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+-----+ | a (陣列名,退化為 int* 指向 0x1000) | +----------------------------------------------------------+ | pa (int*) ────────────────────────────────────────────► 0x1000
ptr + i 移動 i * sizeof(*ptr) 位元組| 運算式 | 型別 | 值/意義 | 位址變化 (int=4) |
|---|---|---|---|
a | int* (退化) | 首元素位址 &a[0] | 0x1000 |
a + i | int* | 指向第 i 個元素 &a[i] | + i*4 |
pa | int* | 同 a,指向 a[0] | 0x1000 |
pa + i | int* | 指向 a[i] | + i*4 |
pa++ | int* (副作用) | 原值 pa,然後 pa 指向下一個元素 | pa 變為 0x1004 |
*pa | int | 解參考,取得 a[0] 的值 | - |
*(pa + i) | int | 等價 pa[i]、a[i] | - |
&a[0] | int* | 首元素位址 | 0x1000 |
&a | int(*)[10] | **整個陣列的位址**,型別不同! | 0x1000 (數值相同,語意不同) |
&a + 1 | int(*)[10] | 陣列結束後位址 0x1000 + 40 | + 40 (整個陣列大小) |
a vs &aint a[10];
printf("%p\n", a); // 0x1000 (int*)
printf("%p\n", &a); // 0x1000 (int(*)[10])
printf("%p\n", a+1); // 0x1004 移動 1 個 int
printf("%p\n", &a+1); // 0x1028 移動 1 個 int[10] (40 bytes)
a (退化) 型別 int*,步長 sizeof(int)。&a 型別 int(*)[10] (指向陣列的指標),步長 sizeof(int[10])。sizeof(a) (得 40)、&a (得陣列指標)。pa++ 的副作用與陷阱int *pa = a;
printf("%d\n", *pa); // a[0]
pa++;
printf("%d\n", *pa); // a[1]
pa++;
printf("%d\n", *pa); // a[2]
// pa 現在指向 a[3],原始陣列起始位址已丟失(除非另存)
**最佳實踐**:使用索引 pa[i] 或暫存指標 int *p = pa; while(*p) ...,避免修改唯一指向陣列開頭的指標。
void func(int arr[]) { } // 等價於 int *arr
void func(int *arr) { } // 同樣
void func(int arr[10]) { } // 10 被忽略,仍退化為 int*
// 內部 sizeof(arr) 為指標大小 (8 bytes 於 64-bit),非陣列大小!
// 傳遞大小需額外參數:void func(int *arr, size_t n)
int b[3][4]; // 3 行 4 列
// b 型別退化為 int(*)[4] (指向包含 4 個 int 陣列的指標)
// b+1 移動 1 行 (16 bytes)
// *b 等價 b[0],型別退化為 int* (指向第 0 行首元素)
// b[i][j] 等價 *(*(b+i)+j) 等價 *(b[i]+j) 等價 b[i][j]
print a, print *a@10 (顯示 10 個元素), print /x pa (十六進位位址)。a,10 (顯示 10 元素)、pa,10、記憶體視窗輸入 &a[0]。C 語言指標與陣列的關係核心在於:**陣列名在表達式中多數退化為指向首元素的指標**,指標運算以**所指型別大小**為步長。理解 a、&a、a+i、pa++ 的型別與語意差異,掌握記憶體連續佈局模型,是寫出正確、高效 C 程式的基石。建議配合圖解記憶體佈局、大量實作指標版字串處理/排序/鏈表操作來內化理解。