在上一篇文章中,我們探討了指針的基本概念。這裡我們通過一組經典問答,進一步鞏固對指針運算的理解。假設有如下代碼片段:
char ch = 'a';
char *pch = &ch;
以下是關鍵表達式的含義解析:
ch 的內存地址。char* 類型的指針變量,其值為 ch 的地址。pch 本身在內存中的地址(二級指針的目標)。pch 進行解引用,間接訪問並獲取 ch 的值(即 'a')。'a',再加 1,結果為 'b'(注意優先級:* 高於 +)。char 大小的內存單元),再解引用訪問該地址上的內容(此處屬於越界訪問,行為未定義)。++(*pch),對指針指向的值進行遞增(ch 變為 'b')。++(*(++pch)),指針先移動,再解引用,最後對目標值遞增。++(*(pch++)),先解引用當前值並遞增,隨後指針移動。理解數組與指針的關係是掌握 C 語言的關鍵一步。請看代碼:
int a[10];
int *pa;
pa = a; // 等價於 pa = &a[0];
這揭示了兩個核心事實:
a 會隱式轉換為指向首元素的指針 &a[0]。pa+1)正是基於這種連續性跳躍到下一個元素。
這是面試與實際開發中極易踩坑的地方:
char amessage[] = "I Love You!"; // 字符數組
char *pmessage = "I Love You!"; // 字符指針

雖然圖示看似相似,但本質區別巨大:
\0)。pmessage[0] = 'i'; 修改內容會導致未定義行為(通常是段錯誤)。核心口訣:數組是“容器”,自帶存儲空間;指針是“路標”,只記錄地址。字符串字面量是常量,存放在只讀區。
適用於數組遍歷與動態內存操作。指針加減整數時,步長為 sizeof(指針指向的類型)。
int values[5];
int *vp;
for (vp = values; vp != &values[5]; ) {
*vp++ = 0; // 清零並移動到下一個
}
只有指向同一數組(或同一塊動態內存)的指針相減才有意義,結果類型為 ptrdiff_t,表示兩者之間的元素個數差值。
int *vp1 = values;
int *vp2 = &values[3];
printf("%td\n", vp1 - vp2); // 輸出 -3
本質是數組,元素為指針。定義形式:類型 *數組名[長度]。
char *ptr_array[10]; // 含有 10 個 char* 的數組

本質是指針,指向一個數組(通常指向二維數組的一行)。定義形式:類型 (*指針名)[長度]。
char ar[3][8] = {"we","are","chinese"}; // 二維數組:連續內存,固定行長
char *parray[3] = {"we","are","chinese"}; // 指針數組:離散內存,行長可變

ar[i][j] 編譯器轉換為 *(*(ar+i)+j)。| 維度 | 指針 | 數組 |
|---|---|---|
| 訪問方式 | 間接訪問(解引用) | 直接訪問(下標) |
| 存儲內容 | 地址 | 數據實體 |
| 結構特性 | 動態數據結構 | 固定大小、同類型元素集合 |
| 內存管理 | malloc/free 手動管理 | 隱式自動分配/釋放 |
| 指向對象 | 可指向匿名數據(堆內存) | 自身即數據 |
a[i] 本質等價於指針偏移 *(a+i)。指針與數組是 C 語言靈活與高效的雙刃劍,深入理解其內存模型,才能寫出健壯、高性能的代碼。