在 C++ 程式設計中,指標與陣列的關係緊密且微妙,掌握它們之間的互動機制是寫出高效、安全程式碼的關鍵。本文將系統梳理陣列指標、元素指標、指標運算、函數參數傳遞以及指標陣列等核心知識點,並輔以實戰程式碼示例,助你建立清晰的記憶體操作模型。
陣列名在本質上代表陣列首元素的地址(即 &a[0])。編譯器在編譯階段會將 a[i] 自動轉換為 *(a + i),這意味著陣列下標訪問實質上是指標運算的語法糖。例如:
int a[10];
int *p = a; // 等價於 p = &a[0]
此時 p + i、a + i 均指向第 i 個元素,解引用後即可讀寫 a[i]。利用指標遍歷陣列能減少指令開銷,生成的目標程式碼更緊湊、執行速度更快。
指標運算中最易混淆的是後置遞增 *p++、前置遞增 *++p 以及 (*p)++ 的區別:
*p++ 等價於 *(p++):先取值,再將指標移向下一個元素。*++p 等價於 *(++p):先移動指標,再取新位置的值。(*p)++:對指標指向的元素值加 1,指標本身不變。只有指向陣列元素的指標才允許進行 ++/-- 運算,否則屬於未定義行為。
將陣列傳遞給函數時,實際傳遞的是首元素地址,因此以下四種形式在語義上等價:
void func(int arr[])void func(int *arr)void func(int *arr)void func(int arr[])注意:函數內部無法直接獲取陣列長度,需額外傳遞大小參數或使用標準容器(如 std::vector)。
指標陣列:陣列元素為指標,例如 char *name[3] = {\"C\", \"C++\", \"Java\"};,常用於儲存字串集合。
指向指標的指標:char **p; 表示 p 指向一個 char* 類型的指標,解引用兩次(**p)可獲得最終的字元資料。此結構常見於命令列參數 char **argv 或動態二維陣列的建立。
std::array、std::vector、std::span(C++20)替代原生陣列,避免指標退化與越界風險。gsl::span 或明確的長度參數界定邊界。nullptr,防止野指標。unique_ptr、shared_ptr)應為動態記憶體管理的首選。深入理解指標與陣列的底層機制,不僅能幫你讀懂經典代碼庫,更能在效能敏感場景下做出正確的抉擇。希望本文能為你的 C++ 進階之路鋪平一塊基石。