2008年8月23日 星期六

如何進行指標 (pointer) 的傳址呼叫(call by reference) (下)

這篇文章介紹函數的傳址呼叫,本文的內容是關於指標變數存放位址的改變。

為什麼要改變指標存放的位址呢,這是個很好的問題,平時在主程式中使用 p = &i;就可以改變其位址值,但是我們要藉著函數呼叫來改變其內容,用途呢?例如你用函數傳入指標來取得新的變數的位址(例如:dequeue(v)呼叫)。但是,有一點要注意的是,指標的值,就像一般整數 int 的值,他們都是屬於傳值呼叫(call by value)的。沒錯,指標也是傳值呼叫。

在下列的C語言範例程式中,modify 收到一個指標 v,然後試著去改變其本身所存放的值,你可以從執行結果看到,ptr的值完全沒有改變,這是當然的,傳值呼叫嗎。要改變其值,必須使用傳址呼叫,所以在 modify2 函數中,注意到了嗎,傳進去的是 int **p ,因為傳進來的是指標變數本身所在的位址,而 **p 表示這個位址中的位址中的值是整數。還可以懂吧。

因此呼叫時,必須傳入指標變數本身的位址,如下所示:
modify2(&ptr);


從執行的結果可以看出,指標的值被函數改變了,好玩吧。
#include <stdio.h>
#include <stdlib.h>

int x=8;
void modify(int *v)
{
v = &x;
}
void modify2(int **p)
{
*p = &x;
}

int main(void)
{
int i = 5, *ptr;
ptr = &i;

printf("Before: ptr=%p, *ptr=%d\n", ptr, *ptr);
modify(ptr);
printf("After: ptr=%p, *ptr=%d\n", ptr, *ptr);
printf("Before: ptr=%p, *ptr=%d\n", ptr, *ptr);
modify2(&ptr);
printf("After: ptr=%p, *ptr=%d\n", ptr, *ptr);

return 0;
}


程式的執行結果如下:

Before: ptr=0022FF74, *ptr=5
After: ptr=0022FF74, *ptr=5
Before: ptr=0022FF74, *ptr=5
After: ptr=00402000, *ptr=8

沒有留言: