新 C 程式設計師的困惑來源之一是指標。乍一看,使用它們似乎沒有多大用處。但是,理解指標至關重要,因為它是一個有用的工具,任何比「Hello, World」程式更大的專案都會有指標。一旦初學者開始掌握指針的概念和適用性,另一波恐怖浪潮就會深入他們的內心:雙指針。

在繼續之前,讓我們回顧一下指標是什麼。

在 C 和其他語言(如 C++)中,指標是保存物件記憶體位址的東西。它們是一個數值,當輸出到控制台時,它們通常以十六進位顯示。這意味著,本質上,指針只是奇特的整數。

現在回到雙指針。

當初學者看到雙指針時,就會開始不舒服地移動,汗水從額頭一直流到下巴。就像生活中其他一切新鮮或陌生的事物一樣,人們一想到要面對以前從未遇到過的事物,就會感到尷尬和不安,即使只是輕微的。但隨著你了解的越多,你開始對自己對想要征服的任何事物的新理解充滿信心。雙指針也是如此。

那麼,什麼是雙指針呢?那麼,如果常規指標要引用記憶體中的物件,那麼雙指標就是指向另一個指標的變數,而另一個指標又指向記憶體中的物件。

例子:

#include <stdio.h>

int main(void)
{
    int value = 100;
    int *value_ptr = &value;
    int **value_double_ptr = &value_ptr;

    printf("Value: %d\n", value);
    printf("Pointer to value: %d\n", *value_ptr);
    printf("Double pointer to value: %d\n", **value_double_ptr);
}

輸出:

~/Desktop 
➜ clang main.c

~/Desktop 
➜ ./a.out     
Value: 100
Pointer to value: 100
Doublue pointer to value: 100

~/Desktop 
➜ 

當取消引用雙指標時,我們不會得到最終物件,而是得到預期的結果:必須再次取消引用才能檢索最終值的指標。它類似於下面的程式碼。

int *ptr = *value_double_ptr;
int final_value = *ptr;

現在我確信大多數剛接觸雙指標的人一定會問自己這樣的問題:「我將在哪裡使用它?」。也許展示雙指標有用性的最佳方法是記住常規指標的實際用途之一。這就是說,常規指標可以用作函數中的輸出參數。如果您不知道的話,輸出參數是一個填充結果的參數。為什麼要使用輸出參數取決於幾個因素,並且超出了本文的範圍,但我覺得這就是可以利用雙指標的地方。

我們將要了解的一個函數是 POSIX getline()函數。其目的是從文件中讀取一行。當讀取該行時,人們可能會懷疑它被返回,但是,情況並非如此,因為返回值用於不同的用途。相反,第一個參數採用雙指針,填入包含該行的緩衝區。

為什麼需要雙指針?因此,它可以分配足夠的記憶體來保存整行加上空終止符。如果記憶體分配和讀取一行成功,則提供的指標將被修改為指向新的且已填入的緩衝區。只有使用雙指針,他們才能實現這一目標。

將任何內容傳遞給函數時,傳遞的是副本而不是實際物件。指針也是如此。如果我們傳遞一個常規指針,我們只能修改該指針指向的內容。如果我們更改指標本身,則更改不會反映在函數外部,因為它是副本。

如果我們想要改變指標指向的位置,我們必須新增另一個間接定址並採用雙指標。

使用getline()的範例如下。

#include <stdio.h> 

int main(void)
{   
    FILE *file = fopen("test", "r");

    char *line = 0;
    int   line_length = 0;
    getline(&line, &line_length, file);

    printf("%s\n", line);
    printf("Line length: %d\n", line_length);
}

getline()有兩個輸出參數:一個用於緩衝區,另一個用於讀入的行的長度。

概括

雙指針對許多初學者來說是一個挑戰。當您對雙指標的概念越來越熟悉並在自己的程式碼中必要時使用它們時,您開始認為曾經害怕雙指標是多麼愚蠢。

現在我將帶著你的新知識送你走!


原文出處:https://dev.to/noah11012/double-pointers-in-cc-2n96


共有 0 則留言