在C語言裡,我們可以使用pointer指向一個實體,因此如果把實體變數的address傳到一個funtion的pointer,那就可以改變此pointer所指向的實體的值。
但是如果我們要改變的不是pointer所指向的實體的值,而是pointer本身的值,那就把pointer當作一種type,再把它的address傳到funtion的double pointer。以下將舉一個例子說明。
假設我們有一個function readData可以從網路抓取packet後,填到一個unsigned型態的的buffer(以pointer傳入),接著我們會使用一個function parse1來分析前半段的buffer,然後在使用function parse2來分析後半段的buffer。在parse的程式碼中,我們使用(buffer++) 來移動buffer的pointer,以利往下讀取資料。
在下面的程式碼中,我們在parse1和parse2都是使用unsigned *buffer來接住main裡的buffer的位址(假設在0x100),因此parse1和parse2接收到的pointer的值都是副本,也就是0x100。所以即使在parse1移動buffer pointer,也不會影響在main的buffer的位址。所以,當parse2呼叫時,傳入buffer pointer的值,依然是0x100,還是從buffer的頭開始分析。
一個錯誤的例子 |
#include <iostream> void readData(unsigned *buffer, int size) // Ex:從網路讀取資料寫道buffer void parse1(unsigned *buffer, int size) // 開始第一階段parse讀取到的資訊 void parse2(unsigned *buffer, int size) // 希望從第一階段的parse後,繼續第二階段的parse int main(void) |
我們可以使用pointer to pointer達到修改pointer的值的目的。方法如下:先使用 unsigned *p = buffer; 來複製一份buffer的address。因此p的值為0x100,並且假設p的address為0x500。然後在parse裡使用unsigned **buffer_p指向p,因使buffer_p的值為0x500。接著我們可以使用(*buffer_p)++來改變p的值,也就是p所指向的位置可以跟個改變。所以在parse1執行完後,p的值,就會改變成0x200,所以再把p的address給parse1後,buffer_p的值雖然一樣式0x500,但是buffer_p所指向的值就變成0x200。因此使用*((*buffer_p)++) 可以指向p,再指向buffer裡實體的unsigned變數。
Note,由於array的address不可以改,所以我們才需要一個p來記錄buffer的address,並且透過修改p的值來達到移動pointer的目的。
一個正確的例子(pointer to pointer) |
#include <iostream> void readData(unsigned *buffer, int size) void parse1(unsigned **buffer_p, int size) void parse2(unsigned **buffer_p, int size) int main(void) |
如果你覺得看不習慣pointer to pointer,可以使用reference to pointer也可以達到同樣目的。請先閱讀這篇:
[C++] Call by value、Call by pointer、Call by reference
一個正確的例子(reference to pointer) |
#include <iostream> void readData(unsigned *buffer, int size) void parse1(unsigned *&buffer, int size) void parse2(unsigned *&buffer, int size) int main(void) |
沒有留言:
張貼留言