今天又徹底地把這部分知識回顧了一下,好好地理解了一番。還是記下來比較靠譜,加深印象,省的以後再忘。
主調函數(比如main函數)中,調用函數(比如numpp函數)時,如果swap的參數在函數中改變了,那麼此參數必須是指針類型的。還是例子好說話。
目的:實現main中的一個整形變量加1。(當然實際情況,如果簡單的功能,不會採取調用函數方式,僅作說明)
錯誤的例子:
void numpp(int x)
{
x++;
}
main()
{
int a=2;
numpp(a);
printf("a=%d\n",a);
}
上述代碼運行結果爲:a=2,並沒有加1。
正確的寫法爲:
void numpp(int *x)
{
(*x)++;
}
main()
{
int a=2;
numpp(&a);
printf("a=%d\n",a);
}
這次的運行結果是正確的:a=3。
這是爲什麼呢?
錯誤的例子分析:main中,a=2,調用numpp函數時,實參a的值傳如x,然後x+1,於是x=3,函數調用結束後,x被釋放掉,而a的值依舊沒有改變,還是2,形參x的值並不會再傳給a,只能實參向形參單向傳送。
正確的例子分析:main中,a=2,&a是a的地址,即指針,調用numpp函數時,a的指針傳送給指針變量x,那麼x就指向了變量a,(*x)++,也就是x指向的變量加1,也就是a+1,變成了3,函數調用結束後,x被釋放掉,但a的變化被保留了下來,所以是加1後的值3。
總結1:“單向傳送”的“值傳遞”方式,就是形參值的改變不能改變實參的值。不可能通過執行調用函數改變實參變量的值,但是可以改變實參指針變量所指向的變量的值。
經驗:爲了使函數中改變了的變量值能被主調函數所用,不能把要改變值的變量作爲函數參數,而應該用指針變量作爲函數參數。在函數執行過程中,使指針變量所指向的變量值發生變化,函數調用結束後,這些變量值的變化依然保留下來。
其實還有一個經典的例子,就是swap函數,交換兩個變量的值。
兩個經典的錯誤:
1、
void swap(int x,int y)
{
int t;
t=x;
x=y;
y=t;
}
main()
{
int a,b;
int *p1=&a,*p2=&b;
swap(p1,p2);
printf("a=%d,b=%d\n",a,b);
}
2、
void swap(int *x,int *y)
{
int *tp;
tp=x;
x=y;
y=tp;
}
main()
{
int a,b;
int *p1=&a,*p2=&b;
swap(p1,p2);
printf("a=%d,b=%d\n",*p1,*p2);
}
例1中的錯誤同最上面的錯誤一樣,必須用指針變量做參數才行。但例2中,就是用指針變量做的參數,但還是不對,下面分析一下:main中,p1指向a,p2指向b,調用函數swap時,p1的值傳送給x,p2的值傳送給y,也就是說x指向a,y指向b,在函數中,x和y作了交換,於是x指向b,y指向a。但是,形參x和y的值並不會回頭再傳給實參p1和p2,所以p1依舊指向a,p2依舊指向b。a和b的值也依舊沒有改變。
總結2:其實本質跟總結1一樣。“單向傳送”的“值傳遞”方式,就是形參值的改變不能改變實參的值。不可能通過執行調用函數改變實參指針變量的值,但是可以改變實參指針變量所指向的變量的值。
最後總結:函數執行過程中,不能通過改變形參變量的值,也不能通過改變形參指針變量的值,來改變實參變量或實參指針變量,而是通過改變形參指針變量指向的變量值,來改變實參變量的值。
如果這句話看明白了,那就真正理解了。
還有一句話可以體會一下:函數的調用,只可以得到一個返回值(即函數值),而使用指針變量做參數,可以得到多個變化了的值。