C 語言中,指標不是單純位址數值,而是「型別 + 位址」的複合體。p + n 表示移動 n * sizeof(*p) 位元組,而非 n 位元組。
int ar[5] = {0,1,2,3,4};
int *p = ar;
printf("%d", *(p + 3 * sizeof(int))); // 錯誤!
分析: p + 3 * 4 = p + 12,指向第 13 個 int (陣列只有 5 個),越界存取未定義行為。
正確寫法: *(p + 3) → 編譯器自動轉為 p + 3 * sizeof(int),正確指向 ar[3] (值 3)。
需求:char *p 指向 int,想跳過該 int 指向下一個 char。
((int *)p)++; // 無效!
原因: 強制轉換 (int *)p 結果是右值 (暫時值),++ 需要左值 (可賦值變數)。實際運作的是原 p (char*),步長仍為 1 位元組。
p += sizeof(int); // char* 步長 1,加 4 位元組正好跳過一個 int
或使用中介變數:
int *ip = (int *)p;
ip++;
p = (char *)ip;
void *vp = malloc(100);
vp + 10; // 編譯錯誤:error C2036: 'void *': unknown size
原因: void 無大小,編譯器無法計算步長。C 標準規定 void* 不支援指標算術。
解法: 轉為具體型別指標:(char *)vp + 10 或 (int *)vp + 10。
int arr[10];
int *p1 = &arr[2];
int *p2 = &arr[7];
ptrdiff_t diff = p2 - p1; // 結果 = 5 (元素個數),非位元組數
指標相減結果型別為 ptrdiff_t (有號整數),表示元素間距。
p + n,勿手動乘 sizeof++/--/= 左值uintptr_t/intptr_t 做整數運算:需位元組級操作時,轉整數運算再轉回指標算術是 C/C++ 核心亦是最大坑源。牢記「型別決定步長」,拒絕手動計算,讓編譯器守護正確性。