今天寢室的山東兄弟在練二級的上機,其中一個題目大概是這樣:在一個函數中,有一個指針形參,記爲*p,然後在函數內部定義了臨時變量a,a和*p是同種類型。經過一系列計算 ,a得到了一個值,這個值最後是需要記錄在指針*p裏面的,應該怎麼保存呢?我當時隨便就說,p=&a。結果發生錯誤了,沒有得到預期結果。正確答案是*p=a。
下面來分析下原因。
學過C的人都知道到,函數的實參與形參的之間是值傳遞,單向傳遞。在譚浩強那本C語言教材中就有這樣一個經典的例子:
void exchange(int x,int y)
{
int temp;
temp=a;a=b;b=temp; //試圖交換a,b
}
exchange(a,b);
cout<<a<<" "<<b<<endl;
輸出的來的仍然是3,4.
要交換a,b,只需改變函數exchange,傳遞a,b的地址,如下:
{
int temp;
temp=*x;*x=*y;*y=temp;
}
這樣,a,b就成功交換了。爲什麼呢?下面再說。
再回到開始提出的那個問題,爲什麼p=&a錯誤而*p=a正確呢?
再看兩段代碼:
using namespace std;
void test_point(int *p)
{
int a=3;
p=&a; // 不同之處
}
int main()
{
int x=4;
int *p1=&x;
test_point(p1);
cout<<*p1<<endl;
}
此時輸出的結果是4,也就是說,指針p1調用test_point函數後值並沒有得到改變,接着看下一段代碼
using namespace std;
void test_point(int *p)
{
int a=3;
*p=a; //不同之處
}
int main()
{
int x=4;
int *p1=&x;
test_point(p1);
cout<<*p1<<endl;
return 0;
}
此時輸出結果是3,證明指針p1在調用test_point函數後得到改變。
不難發現,兩段代碼不同之處在於函數中對p的處理,一個是p=&a,一個是*p=a,有什麼區別呢?
翻開C++ primer(第四版)105頁可以發現其中的解釋:
對p=&a,稱之爲給指針賦值,意思是給指針本身一個指向的對象。
而對*p=a稱之爲通過指針進行賦值,意思是改變指針所指對象的值。
有了上面的基礎就很好解釋了,p=&a是相當於把函數的形參指針p指向a(即給指針賦值,此值是a的地址),但由於a是臨時變量,函數調用完後即不存在了,所以實參p1是不會被改變的,*p1=4。
而*p=a就不同了,我們知道,函數是值傳遞,實參p1傳遞給形參p的值是什麼呢?當然是x的地址,也就是說,在函數test_point調用的過程中,形參指針p指向了x,然後進行的*p=a是通過指針進行賦值,改變了p指向的對象x,p1仍然指向x,故*p1=3.
這樣,那個exhange函數也很好解釋了,也就是一個通過指針進行賦值的問題。