題目代碼
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf("ptr1[-1] = %d, *ptr2 = %d\n", ptr1[-1], *ptr2);
記憶體佈局圖解
位址假設:a 起始於 0x1000
int 佔 4 位元組
a[0] 0x1000 值 1
a[1] 0x1004 值 2
a[2] 0x1008 值 3
a[3] 0x100C 值 4
a[4] 0x1010 值 5
陣列結束 0x1014
關鍵表達式解析
| 表達式 | 型別 | 數值(假設 a=0x1000) | 含義 |
a | int * | 0x1000 | 首元素位址 |
&a | int (*)[5] | 0x1000 | 整個陣列位址 |
a + 1 | int * | 0x1004 | 下一個 int |
&a + 1 | int (*)[5] | 0x1014 | 跨過整個陣列(5*4=20 位元組) |
(int)a + 1 | int (整數) | 0x1001 | 位址值 + 1 位元組 |
ptr1 與 ptr2 實際指向
ptr1 = (int *)(&a + 1) → 0x1014(陣列尾部下一個位址)
ptr1[-1] 等價 *(ptr1 - 1) → 0x1010 → a[4] = 5
ptr2 = (int *)((int)a + 1) → 0x1001(a[0] 位址 + 1 位元組)
*ptr2 讀取 0x1001 起始的 4 位元組 → 0x02000000(小端序,視機器而定),非陣列元素,屬未定義行為。
輸出結果(典型小端機器)
ptr1[-1] = 5, *ptr2 = 33554432 // 0x02000000 = 33554432
核心知識點總結
&a 型別為「指向含 5 個 int 陣列的指標」,步長 = 整個陣列大小。
a 退化為「指向 int 的指標」,步長 = sizeof(int)。
- 強制轉型為
int 再 +1 是位元組級運算,破壞型別安全。
ptr1[-1] 是合法取陣列最後一元素技巧;*ptr2 為嚴重錯誤。
延伸練習
int a[2][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = a;
printf("%d\n", *(*p+1)); // 2
printf("%d\n", *(*(p+1)+2)); // 6