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

C++ 二級指標深度解析:指標的指標、參數傳遞修改指向與記憶體圖解

     編輯:關於C語言

二級指標(T**)是「指向指標的指標」,除能修改所指物件值外,更能修改一級指標的指向。本文從記憶體模型出發,對比一級/二級指標作為函數參數的語意差異,提供完整圖解與三種實戰範例,徹底釐清指標層級操作邏輯。

記憶體模型圖解

int m = 4, n = 5;
int *p = &m;          // p 存放 m 位址
int **q = &p;         // q 存放 p 位址

記憶體佈局:
q (位址 0x7000) ──► p (位址 0x6000) ──► m (位址 0x5000, 值 4)
                           │
                           └──► (可修改為 &n)
  • *q 等價於 p(一級指標值)。
  • **q 等價於 *p 等價於 m(最終物件值)。

函數參數傳遞對比

參數型別能修改物件值能修改呼叫端指標指向典型用途
int* (一級)✅❌ (傳值,副本)輸出參數、陣列處理
int** (二級)✅✅ (傳址,原指標)輸出指標、雙向鏈表頭插、工廠函數

範例 1:函數內修改呼叫端一級指標指向

#include <iostream>
using namespace std;

int num = 8;

void changePtr(int** pp) {   // 接收一級指標的位址
    *pp = &num;              // 解引用一次,修改原 p 的指向
}

int main() {
    int a = 5;
    int* p = &a;
    changePtr(&p);           // 傳遞 p 的位址
    cout << *p << ' ' << a; // 輸出:8 5  (p 已指向 num,a 不變)
}

範例 2:一級指標參數只能修改物件值


void changeVal(int* p) {
    int i = 0;
    int* tmp = &i;
    *p = 8;       // 修改物件值
    p = tmp;      // 只修改區域副本,呼叫端 p 不受影響
}

int main() {
    int a = 5;
    int* p = &a;
    changeVal(p);
    cout << *p << ' ' << a; // 輸出:8 8  (a 被改為 8,p 仍指向 a)
}

範例 3:綜合操作演示


void modify(int* p, int** q, int* z) {
    int a = 10;
    z = &a;           // 只修改區域 z 指向,不影響呼叫端
    *p = 10;          // 修改 p 指向的物件值
    **q = a;          // 修改 q 指向的指標所指物件值
    // *q = &a;       // 若取消註解,可修改呼叫端一級指標指向
    cout << "函數內: *p=" << *p << " **q=" << **q << endl;
}

int main() {
    int i=4, j=5, k=6;
    int *p=&i, *q=&j, *z=q;  // z、q 同指向 j
    *z = 8;                  // j 變 8
    z = &k;                  // z 改指向 k,q 仍指向 j
    cout << "呼叫前: *p=" << *p << " *q=" << *q << endl;
    modify(p, &q, z);        // 傳 q 位址
    cout << "呼叫後: *p=" << *p << " *q=" << *q << endl;
}

輸出解析:

  • *p (i) 從 4 → 10
  • *q (j) 從 8 → 10 (經 **q = a)
  • z 區域修改不影響外部

核心口訣

一級指標傳值:改值不改向。
二級指標傳址:改值又改向。

實際應用場景

  1. 動態分配輸出指標:int createNode(Node** out) 由函數分配並回傳新節點位址。
  2. 鏈表頭插入:void push(Node** head, int val) 修改 *head 指向新節點。
  3. 二維動態陣列:int** arr = new int*[rows],每列再 new int[cols]。
  4. COM/Win32 API:HRESULT CreateInstance(IUnknown** ppv) 標準輸出介面指標模式。

總結

二級指標的本質是「指標的地址」。掌握 *pp 解引用一次得到一級指標、**pp 解引用兩次得到物件的雙重解引用機制,即可靈活實現「函數修改呼叫端指標指向」等進階模式。圖解記憶體、對比參數傳遞語意、多寫實戰範例,是攻克指標層級操作的最佳路徑。

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