指標是 C/C++ 區別於高階語言的核心特性,直指硬體記憶體模型。本文從 CPU 執行觀點重構指標概念:數值、位址、類型修飾符、間接層級,系統闡述一維/多維陣列與指標運算的等價性、多級指標記憶體佈局、函數指標與回調機制、成員指標的特殊語義,並以「間接層級」統一解釋靈活性、效率、語義表達三大運用目的。
指令碼 10100(十進位 20)在 ALU 中僅為電壓高低組合;編譯器依類型決定位元解讀規則(原碼/補碼/IEEE-754)。
*(指標):忽略原類型,將數值視為 32/64 位元位址,長度固定 4/8 位元組[](陣列):重複原類型 N 次,連續儲存,數值為首元素位址&(引用):編譯期別名,無執行期儲存const、__stdcall、Class::(成員偏移)等修飾順序:從左至右,同類連續修飾從右至左(符合宣告閱讀習慣)。
變數 long a; 對應位址 3000。a = 3; 實際執行:取得位址類型數值 3000 → 依 long 規則寫入 4 位元組。變數名即位址類型數值的操作符。
long* p = a; // 隱式轉換:long[3] → long*
*(p+1) = 4; // 等價 a[1] = 4
p[-1] = 3; // 合法:位址 - sizeof(long)
p + n 返回 p + n * sizeof(*p),型別保持 long*。
[] 只是語法糖a[i] ≡ *(a + i) ≡ *(i + a) ≡ i[a]。前置運算元必須可隱式轉為指標。
long a[2][3]; // 48 位元組連續
long (*p)[3] = a; // 指向長度 3 陣列的指標
a[1][2] ≡ *(*(a+1)+2) ≡ *(*p+1+2) ≡ p[1][2]
關鍵:a + 1 跳過 sizeof(long[3]) = 12 位元組。
long a = 0; // 3000
long* p = &a; // 3004,值 3000
long** pp = &p; // 3008,值 3004
long*** ppp = &pp; // 3012,值 3008
*(*(pp+1)) 先 pp+1 → 3012,再解引用兩次 → 修改 p 的值long (*ap)[2][3] 仍是單一 4/8 位元組指標,指向 48 位元組區塊| 目的 | 機制 | 典型場景 |
|---|---|---|
| 增加靈活性 | 同一程式碼、不同位址 → 不同結果 | 迴圈處理分散緩衝區、函數指標表驅動、虛函數表 |
| 引用記憶體區塊 | 傳遞首址而非複製資料 | bool GetInfo(Info* out)、大型結構輸出參數 |
| 引用數值(二級間接) | 指標 → 位址類型 → 數值,傳 4/8 位元組替代大型物件 | void Sort(int* arr, int n)、const BigObj* p |
| 語義表達 | 程式碼直接映射領域概念 | 鏈結串列 next、樹狀 left/right、觀察者模式回調 |
typedef int (__stdcall *PFN_CMP)(const void*, const void*);
void QuickSort(void* base, size_t n, size_t sz, PFN_CMP cmp); // qsort 原型
// 回調模式
bool Search(bool(*onTimeout)(unsigned sec), ...); // 超時詢問
bool MyTimeout(unsigned s) { return s < 30; }
Search(MyTimeout, ...);
struct Student { float score[40]; };
float Student::* pScore = &Student::score[0]; // 單一成員
float Student::* pArr[40] = { &Student::score[0], ... }; // 陣列
Student s;
for (int i=0; i<40; ++i) sum += s.*pArr[i]; // .* 運算子
this 調整位移(多重繼承、虛繼承),尺寸可達 8/16/24 位元組NULL/0/nullptr(C++11)表示「無效位址」std::unique_ptr/shared_ptr 以 RAII 消除手動管理HANDLE/void* + C 風格 API指標本質是帶有類型修飾的位址數值,透過間接層級實現靈活性與效率的平衡。深入理解「修飾順序、運算規則、記憶體佈局、語義對應」,即能駕馭從底層驅動到高階架構的所有指標應用場景。現代 C++ 建議:能用引用/智慧指標/容器/演算法者,盡量不用裸指標。