C 語言中的指向指針的指針(雙重指針)

你好,有抱負的程序员!今天,我們將進入指針的世界——特別是指向指針的指針。我知道你可能在想什麼:“指針?雙重指針?這聽起來像個夢魘!”但別擔心,我保證會讓這個主題變得有趣且容易理解。所以,拿起你最喜歡的飲料,放鬆一下,我們一起深入探討吧!

C - Pointer to Pointer

C 語言中的雙重指針是什麼?

想象一下你正在參加尋寶遊戲。你有一張地圖(我們稱之為指針),它引導你到達一個寶箱。但驚喜!在寶箱裡,還有另一張地圖(另一個指針),它會引導你到達真正的寶藏。這基本上就是雙重指針的概念——一個指向另一個指針的指針。

在 C 語言編程中,雙重指針正如其名——一個指向指針的指針。它是一個變量,用於存儲另一個指針的地址。這聽起來可能一開始會有些混亂,但別擔心,我們會一步一步來解析。

指向指針的指針的聲明

我們先從如何聲明雙重指針開始。語法非常直接:

int **ptr;

在這裡,ptr 是一個指向指針的指針,該指針指向一個整數。第一個星號 * 讓它成為一個指針,第二個 * 讓它成為一個指向指針的指針。

指向指針(雙重指針)的示例

我們來看一個簡單的例子來更好地理解這一點:

#include <stdio.h>

int main() {
int x = 5;
int *p = &x;
int **pp = &p;

printf("x 的值:%d\n", x);
printf("使用 p 顯示 x 的值:%d\n", *p);
printf("使用 pp 顯示 x 的值:%d\n", **pp);

return 0;
}

輸出:

x 的值:5
使用 p 顯示 x 的值:5
使用 pp 顯示 x 的值:5

讓我們來解析一下:

  1. 我們聲明了一個整數 x 並將其初始化為 5。
  2. 我們創建了一個指針 p,它指向 x
  3. 我們創建了一個雙重指針 pp,它指向 p
  4. 然後我們以三種不同的方式列印出 x 的值:
  • 直接使用 x
  • 使用單一指針 p(我們用 *p 進行一次解引用)
  • 使用雙重指針 pp(我們用 **pp 進行兩次解引用)

這三種方法都會得到相同的值:5。這就像使用不同的地圖找到寶藏一樣!

C 語言中的普通指針是如何工作的?

在我們進一步探討雙重指針之前,先快速複習一下普通指針是如何工作的:

int y = 10;
int *q = &y;

printf("y 的值:%d\n", y);
printf("y 的地址:%p\n", (void*)&y);
printf("q 的值:%p\n", (void*)q);
printf("q 指向的值:%d\n", *q);

輸出:

y 的值:10
y 的地址:0x7ffd5e8e9f44
q 的值:0x7ffd5e8e9f44
q 指向的值:10

在這裡,q 是一個存儲 y 地址的指針。當我們使用 *q 時,我們正在訪問存儲在該地址的值。

雙重指針是如何工作的?

現在我們將這個概念延伸到雙重指針:

int z = 15;
int *r = &z;
int **rr = &r;

printf("z 的值:%d\n", z);
printf("z 的地址:%p\n", (void*)&z);
printf("r 的值:%p\n", (void*)r);
printf("r 的地址:%p\n", (void*)&r);
printf("rr 的值:%p\n", (void*)rr);
printf("r 指向的值:%d\n", *r);
printf("rr 指向的值:%p\n", (void*)*rr);
printf("rr 指向的指針的值:%d\n", **rr);

輸出:

z 的值:15
z 的地址:0x7ffd5e8e9f48
r 的值:0x7ffd5e8e9f48
r 的地址:0x7ffd5e8e9f50
rr 的值:0x7ffd5e8e9f50
r 指向的值:15
rr 指向的值:0x7ffd5e8e9f48
rr 指向的指針的值:15

這可能看起來有點複雜,但讓我們來解析一下:

  1. z 是一個值為 15 的整數。
  2. r 是一個存儲 z 地址的指針。
  3. rr 是一個存儲 r 地址的雙重指針。
  4. *r 給我們 z 的值(15)。
  5. *rr 給我們 r 的值(即 z 的地址)。
  6. **rr 給我們 z 的值(15)。

這就像這樣:rr 指向 rr 指向 z。所以 **rr 就像在說“跟隨第一個指針,然後跟隨第二個指針,並給我那裡的值”。

雙重指針行為與普通指針一樣

這裡有一個小秘密:雙重指針只是一個指針,但它指向的是另一個指針,而不是整數或浮點數。這意味著我們可以對雙重指針進行所有與普通指針相同的操作。

例如,我們可以在數組中使用雙重指針:

int main() {
char *fruits[] = {"Apple", "Banana", "Cherry"};
char **ptr = fruits;

for(int i = 0; i < 3; i++) {
printf("%s\n", *ptr);
ptr++;
}

return 0;
}

輸出:

Apple
Banana
Cherry

在這個例子中,fruits 是一個指向字符串的指針數組,而 ptr 是一個指向字符指針的指針(可以指向 fruits 的元素)。

C 語言中的多級指針(三重指針可能嗎?)

是的,你可以有三重指針、四重指針等等!理論上,指針的間接層次沒有限制。然而,在實際應用中,很少會看到超過雙重指針的情況。

這裡有三重指針的例子:

int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;

printf("x 的值:%d\n", ***ppp);

輸出:

x 的值:5

但記住,只是因為你可以這樣做,並不代表你應該這樣做。多個間接層次會使代碼更難以閱讀和維護。正如古老的編程諺語所說:“計算機科學中的所有問題都可以通過另一個間接層次來解決……除了間接層次太多的問題!”

結論

恭喜你!你剛剛順利穿越了 C 語言中複雜的雙重指針水域。記住,就像編程中的許多概念一樣,指向指針的指針可能一開始會讓人感到困惑,但通過練習,它們將變得 second nature。

以下是本文涵蓋的重點的摘要表格:

概念 語法 描述
普通指針 int *p; 指向一個整數
雙重指針 int **pp; 指向一個指向整數的指針
解引用 *p 訪問 p 指向的值
雙重解引用 **pp 訪問 pp 指向的指針指向的值
地址運算符 &x 獲取 x 的地址

繼續練習,保持好奇心,並記住——每個專家都曾是初學者。快樂編程!

Credits: Image by storyset