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

C++ 指針深度解析:從數字、地址到多級指針、函數指針與成員指針完整語義

     編輯:VC 教學

核心概念重構

在 C++ 抽象機中:

  • CPU 只識別狀態,二進制數是狀態的編碼,指令是狀態轉換規則。
  • 類型 = 「如何將數學數值編碼為二進制」的規則 (如 int 用補碼,float 用 IEEE-754)。
  • 類型修飾符 = 在原類型基礎上改變編碼/解釋規則的二階操作:* (指針)、& (引用)、[] (數組)、() (函數)、::* (成員指針)、const 等。
  • 地址類型 (編譯期概念) = 某類型值在內存中的位置,編碼為機器字寬 (32/64 位) 無符號整數。

指針類型修飾符語義

T* 表示:「將一個數值按無符號整數編碼 (機器字寬),視為內存地址;解引用時按 T 的規則解釋該地址起始的位模式。」

  • 指針值本身**不依賴原類型 T** (故所有指針同寬)。
  • *p (解引用) = **類型轉換**:將 T* 型值轉為 T 的**地址類型**值 (地址不變,類型變)。
  • &x (取址) = **類型轉換**:將 T 的**地址類型**值轉為 T* 型值。
  • 因此 &*p == p、**不訪問內存**,純編譯期類型轉換。

指針運算與數組的本質關係

  • p + n = 地址值 + n * sizeof(T) (按元素步進)。
  • a[n] ≡ *(a + n) ≡ *(n + a) ≡ n[a]。
  • 數組類型 T[N] 隱式轉換為 T* (退化為首元素地址),**但丟失長度信息**。
  • sizeof(T[N]) == N*sizeof(T),sizeof(T*) == 機器字寬。

多級指針

int  a = 10;
int *p1 = &a;      // int*
int **p2 = &p1;    // int**
int ***p3 = &p2;   // int***
// ***p3 === a
// 每級解引用剝離一層 *,地址值不變,類型逐級變化。

函數指針

類型修飾符 () 表示「可調用實體」,參數列表與返回類型構成函數類型。

// 普通函數指針
int (*pf)(double, char); // 指向 int(double,char) 的指針

// 成員函數指針 (需類作用域)
struct A { void foo(int); };
void (A::*pmf)(int) = &A::foo;
(A.*pmf)(42); // 物件調用
(pA->*pmf)(42); // 指針調用

**成員函數指針非單純地址**,可能包含 this 偏移、虛表索引等 (實現定義),**大小不固定**,不可轉換為 void*。

數組指針 vs 指針數組

int (*pa)[10]; // 指向 int[10] 的指針 (數組指針)
int *ap[10];   // 10 個 int* 的數組 (指針數組)
// 讀法:從變量名出發,先看右邊 []/(),再看左邊 *。

成員指針 (Data Member Pointer)

struct S { int x; double y; };
int S::*pmx = &S::x; // 偏移量編碼
double S::*pmy = &S::y;
S obj; S* p = &obj;
obj.*pmx = 1;  // 直接訪問
p->*pmx = 2;   // 通過指針訪問
// 多繼承/虛繼承下可能包含多個偏移量 + vbptr 索引,大小 > 機器字寬。

常見誤區正本清源

誤區真相
指針就是地址指針 = 地址值 + 類型信息 (編譯期);void* 只有地址值,無類型信息
*p 訪問內存*p 是類型轉換,**編譯期**動作;實際內存訪問由後續賦值/讀取指令觸發
數組就是指針數組有長度、占用連續存儲、sizeof 為總大小;退化為指針時丟失長度
函數指針可轉 void*標準禁止;實踐中常違規但不可移植 (如 dlsym 返回 void*)
成員指針 = 偏移量單繼承非虛基類才是純偏移;多繼承/虛繼承包含額外調度信息

現代 C++ 最佳實踐

  • **避免裸指針擁有所有權**:用 std::unique_ptr/shared_ptr 管理生命週期。
  • **非擁有觀察**:用 T* (可空) / T& (非空) / std::span (數組視圖) / std::function (可調用物)。
  • **成員指針**:配合 std::invoke/std::mem_fn 實現泛化調用。
  • **C 風格接口互操作**:邊界處轉換,內部用現代設施。

總結

指針是 C++ 類型系統中最強大、最危險的修飾符。理解其「類型轉換本質、地址運算規則、退化行為、成員指針特殊編碼」,才能寫出正確、高效、可維護的現代 C++ 代碼。

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