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

C語言指針進階:指向指針的指針(雙重指針)詳解與實戰應用

     編輯:關於C語言

指向另一指針的指針:核心概念

在《徹底搞定C語言指針》系列的第二篇中,我們已經深入剖析了指針的本質。今天我們將邁進更高階的領域——學習「指向另一指針地址的指針」,也就是常說的雙重指針或指針的指針。在正式開始前,讓我們快速回顧一下指針的基礎模型。

回顧:指針的內存模型

當程序聲明變量時:

short int i;
char a;
short int *pi;

編譯器會在內存中為每個變量分配空間。假設內存地址從 6 到 15,佈局如下:

內存地址 → 6  7  8  9  10 11 12 13 14 15
--------------------------------------------------
... |    |    |    |    |    |    |    |    |    |
--------------------------------------------------
    |short int i|char a|      |short int *pi|
  • i 位於地址 6,佔 2 字節(短整型)
  • a 位於地址 8,佔 1 字節
  • pi 位於地址 10,佔 2 字節(此處假設 16 位系統,32 位系統為 4 字節)

執行賦值:

i = 50;
pi = &i;

內存映像變為:

內存地址 → 6  7  8  9  10 11 12 13 14 15
--------------------------------------------------
... | 50 |    |    |  6 |    |    |    |    |    |
--------------------------------------------------
    |short int i|char a|      |short int *pi|

此時 pi 的值為 6,即 i 的起始地址。對 *pi 的讀寫實際上就是對 i 的讀寫,例如 *pi = 5; 等價於 i = 5;。

指針的地址與雙重指針

指針變量本身也佔據內存地址(如 pi 在地址 10)。我們可以聲明另一個指針指向這個地址:

short int **ppi;  // 注意兩個 * 號
ppi = π
  • 第一行:聲明 ppi 為「指向 short int * 類型指針的指針」
  • 第二行:取 pi 的地址(10)賦給 ppi

更新後的內存佈局:

內存地址 → 6  7  8  9  10 11 12 13 14 15
--------------------------------------------------
... | 50 |    |    |  6 | 10 |    |    |    |    |
--------------------------------------------------
    |short int i|char a|      |short int *pi|short int **ppi|

關鍵解引用關係

表達式值含義
ppi10指針 pi 的地址
*ppi6pi 的值(即 i 的地址)
**ppi50i 的值(即 *pi 的值)

這層層解引用的機制,正是雙重指針的核心威力所在。

實戰案例:函數中修改指針參數

問題場景

設計函數 find1(char array[], char search, char *pi):在以 \0 結尾的字符串 array 中查找字符 search,找到則通過第三個參數返回該字符地址,否則返回 0。

void find1(char array[], char search, char *pa) {
    int i;
    for (i = 0; *(array + i) != 0; i++) {
        if (*(array + i) == search) {
            pa = array + i;
            break;
        } else if (*(array + i) == 0) {
            pa = 0;
            break;
        }
    }
}

調用測試

void main() {
    char str[] = "afsdfsdfdf\0";
    char a = 'd';
    char *p = 0;
    find1(str, a, p);
    if (0 == p) {
        printf("沒找到!\n");
    } else {
        printf("找到了,p=%d", p);
    }
}

運行結果輸出「沒找到!」——明明字符串第 4 個字符是 'd',為什麼失敗?

根因分析

函數調用時發生隱含賦值:

array = str;
search = a;
pa = p;   // 值傳遞:pa 獲得 p 的地址值(此處為 0)

函數內部修改 pa 只是改變了形參的局部副本,無法影響實參 p 的值。這正是「值傳遞」的限制——即使傳遞的是地址值,也是按值傳遞地址。

解決方案:雙重指針

改用 char **ppa 作為參數,調用時傳遞 &p:

void find2(char array[], char search, char **ppa) {
    int i;
    for (i = 0; *(array + i) != 0; i++) {
        if (*(array + i) == search) {
            *ppa = array + i;  // 解引用一次,修改 p 的值
            break;
        } else if (*(array + i) == 0) {
            *ppa = 0;
            break;
        }
    }
}

// 主函數調用
find2(str, a, &p);

調用時的隱含賦值變為

array = str;
search = a;
ppa = &p;   // ppa 指向 p 的地址

函數內對 *ppa 的修改直接作用於 p,從而實現「在函數內修改指針變量本身」的目的。這是雙重指針最經典的應用場景之一。

總結

  • 指針的指針聲明形式為 類型 **變量名
  • 它存儲另一個指針的地址,通過 * 可訪問該指針的值,** 可訪問最終目標數據
  • 核心用途:在函數中修改指針參數的指向、動態二維數組、命令行參數 char **argv 等
  • 理解「值傳遞」與「指針傳遞」的區別是靈活運用雙重指針的關鍵

掌握雙重指針,標誌著你已跨越 C 語言指針學習的重要門檻,能夠處理更複雜的內存管理與數據結構問題。

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