指針加減整數不是簡單的字節偏移,而是按指向類型大小縮放。本文通過實測代碼、記憶體地址變化圖解、三種遍歷方式對比,徹底講透指針算術的規則與陷阱。
ptr + n→ 新地址 =ptr + n * sizeof(*ptr)
ptr - n→ 新地址 =ptr - n * sizeof(*ptr)
結果指針類型、指向類型不變;步長 = sizeof(指向類型)。
#include
int main() {
char str[] = {'a','b','c','d','e'};
int *p = (int*)str; // 強轉為 int*
char *q = str; // char*
printf("str 首地址: %p\n", (void*)str); // 0x7ffd...
printf("q 初始: %p\n", (void*)q); // 同 str
printf("p 初始: %p\n", (void*)p); // 同 str
q++; // +1 byte
p++; // +4 bytes (sizeof(int))
printf("q++ 後: %p (差 %td)\n", (void*)q, q - (char*)str); // +1
printf("p++ 後: %p (差 %td)\n", (void*)p, p - (int*)str); // +1 (但實際字節 +4)
return 0;
}
輸出示例:
str 首地址: 0x7ffd12345670
q 初始: 0x7ffd12345670
p 初始: 0x7ffd12345670
q++ 後: 0x7ffd12345671 (差 1)
p++ 後: 0x7ffd12345674 (差 1,但字節跨度 4)
| 方式 | 代碼模式 | 適用指針類型 | 備註 |
|---|---|---|---|
| 下標法 | arr[i] | 數組名 | 最直觀 |
| 數組名+偏移 | *(arr + i) | 數組名 | arr 退化為首元素指針 |
| 獨立指針 | for (p=arr; p<arr+len; ++p) *p | 指向元素類型的指針 | 需類型匹配,q 可遍歷 char[],p 不可 |
int *p = (int*)char_arr; p++ 跳過 4 字節,導致漏讀/越界。ptrdiff_t(有符號),表示元素個數差,非字節差。p2 - p1 == (char*)p2 - (char*)p1) / sizeof(*p1)char* 再運算。arr + len),其他均為 UB。size_t/ptrdiff_t。int arr[10];
int *p1 = &arr[2], *p2 = &arr[7];
ptrdiff_t diff = p2 - p1; // 5 (元素個數)
size_t bytes = (char*)p2 - (char*)p1; // 20 (字節數)
指針算術的本質是 「元素級偏移」。牢記 ptr ± n → ± n * sizeof(*ptr) bytes,配合 char* 做字節級操作、ptrdiff_t 存差值、嚴守數組邊界,即能安全、高效地玩轉指針運算。