首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 指標深度解析:從記憶體模型到語義運用——多級指標、函數指標、成員指標完全指南

     編輯:關於C++

指標是 C/C++ 區別於高階語言的核心特性,直指硬體記憶體模型。本文從 CPU 執行觀點重構指標概念:數值、位址、類型修飾符、間接層級,系統闡述一維/多維陣列與指標運算的等價性、多級指標記憶體佈局、函數指標與回調機制、成員指標的特殊語義,並以「間接層級」統一解釋靈活性、效率、語義表達三大運用目的。

一、基礎概念重構

1. CPU 僅識別狀態,非數學數值

指令碼 10100(十進位 20)在 ALU 中僅為電壓高低組合;編譯器依類型決定位元解讀規則(原碼/補碼/IEEE-754)。

2. 類型修飾符:層層包裝的解讀規則

  • *(指標):忽略原類型,將數值視為 32/64 位元位址,長度固定 4/8 位元組
  • [](陣列):重複原類型 N 次,連續儲存,數值為首元素位址
  • &(引用):編譯期別名,無執行期儲存
  • const、__stdcall、Class::(成員偏移)等

修飾順序:從左至右,同類連續修飾從右至左(符合宣告閱讀習慣)。

3. 位址類型數值:間接的起點

變數 long a; 對應位址 3000。a = 3; 實際執行:取得位址類型數值 3000 → 依 long 規則寫入 4 位元組。變數名即位址類型數值的操作符。

二、指標與陣列的雙重身分

1. 指標運算 = 位址 + 元素尺寸 × 整數

long* p = a;     // 隱式轉換:long[3] → long*
*(p+1) = 4;      // 等價 a[1] = 4
p[-1] = 3;       // 合法:位址 - sizeof(long)

p + n 返回 p + n * sizeof(*p),型別保持 long*。

2. 下標運算子 [] 只是語法糖

a[i] ≡ *(a + i) ≡ *(i + a) ≡ i[a]。前置運算元必須可隱式轉為指標。

3. 多維陣列 = 連續記憶體 + 編譯期位移計算

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
  • 每級指標固定 4/8 位元組,僅儲存下一級位址
  • *(*(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、觀察者模式回調

五、進階指標類型

1. 函數指標:介面的引用

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, ...);

2. 成員指標:偏移的引用

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)表示「無效位址」
  • 使用前必須檢查if (p) { ... }
  • 智慧指標 std::unique_ptr/shared_ptr 以 RAII 消除手動管理
  • 跨 DLL 介面禁用 C++ 類別指標,改用 HANDLE/void* + C 風格 API

七、總結

指標本質是帶有類型修飾的位址數值,透過間接層級實現靈活性與效率的平衡。深入理解「修飾順序、運算規則、記憶體佈局、語義對應」,即能駕馭從底層驅動到高階架構的所有指標應用場景。現代 C++ 建議:能用引用/智慧指標/容器/演算法者,盡量不用裸指標。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved