第四十七章 指針(二)
「理論上應該沒有問題的呀,要實現(xiàn)交換兩個變量的值容易得很!可是老爹的笑容讓我心里一陣發(fā)毛……這其中絕對有貓膩!」
面對老爹提出的疑問,原本信心滿滿地我瞬間失去了所有的底氣。一旁的小弦子雖然沒有吭聲,眉頭卻是皺得跟個小老頭兒似的。
有道是實踐是檢驗檢驗真理的唯一準則,是騾子是馬,拉出來溜溜不就知道結果了么?
于是乎我三下五除二就寫好了swap函數(shù),為了謹慎起見,我還在函數(shù)中打印了交換前后的值。
以我如今的水品寫這種簡單的代碼出錯的幾率還是很小的,編譯運行一氣呵成,小黑屏上打印出來的結果的的確確顯示兩個變量的值已經(jīng)成功交換了。
「這是幾個意思?難道老爹是在故布疑陣,唱空城計?」
小弦子看到我咬手指甲,面露沉思,于是也把腦袋湊過來看了一眼顯示屏,隨即開始捏著下巴冥思苦想。
「老爹,打印的結果明明顯示交換成功了呀!」
為了穩(wěn)妥起見,我還進行了單步調試,可是一切都按照預期的流程執(zhí)行,結果也是預期的結果。最終我還是沒有發(fā)現(xiàn)問題到底出在哪里,于是只能向老爹求助。
「我可沒有讓你打印形式參數(shù)x,y的值,我說的是交換實際參數(shù)a和b的值,也就是這樣:
int a = 3;
int b = 4;
swap(a,b);
printf(“a =%d\n“, a);
printf(“b =%d\n“, b);」
「橋豆麻袋,形式參數(shù)……實際參數(shù)又是從哪兒冒出來的新名詞???」
「哦,這點是我的疏忽,在給你們講函數(shù)這一部分知識的時候忘了說。函數(shù)參數(shù)列表中的變量叫做形式參數(shù),比如說:
swap(int x, int y)
這里的x和y就就做形式參數(shù)。
而我們在調用函數(shù)時,為函數(shù)傳遞的參數(shù),這個就叫實際參數(shù),例如:
swap(a,b)
a和b就是實際參數(shù)。
而我剛剛提出的要求是要交換兩個是實際參數(shù)的變量,所以我們應該監(jiān)控a和b在調用函數(shù)的前后的變化?!?p> 明白了老爹的意圖后,我對代碼進行了更改,然后重新編譯、運行。
「WHAT!」
看到小黑屏上打印的結果后,我沒有忍住喊了出來。因為屏幕上打印的結果顯示,a和b在調用swap函數(shù)前后居然沒有任何變化!我簡直不敢相信自己的眼睛,這就好比你用計算器計算1+1的值,它妹的居然給你顯示1+1=3!
為了委托期間,我重啟了電腦又執(zhí)行了幾次,但是結果都是一樣的!換句話說,swap函數(shù)交換a和b的值失敗了,但是函數(shù)分明已經(jīng)是執(zhí)行了的!
「老爹,這是怎么回事兒?。俊?p> 我實在是想不通這其中的癥結所在,只能夠向老爹提問。
「這就要從函數(shù)參數(shù)的傳遞問題開始說起了。
在C語言中,我們在調用函數(shù)的時候,參數(shù)的傳遞實際上是采用的值的傳遞方式,什么意思呢?
就拿我們剛剛舉那個例子來說,當我們在調用swap(a,b)的時候,實際上是把a的值3復制了一份給變量x,而不是a這個變量換了一個名字,變成了x。同理,變量b的值4復制了一份給y。而x和y跟a和b沒有任何關系,所以在函數(shù)中無論我們對x和y做什么操作,都不會影響到a和b,所以對a和b進行值交換沒有成功?!?p> 「原來如此!那用指針為什么就能達到這個效果呢?」
我點了點頭,然后拋出了自己的疑問。
「誒,我什么時候說了用指針可以實現(xiàn)這個功能?」
「雖然任叔叔你沒有明說,但是你特地挖了一個坑讓我和玥玥往里面跳,肯定是別有目的的。既然現(xiàn)在咱們正好在學習指針,再加上剛剛我和玥玥都對指針的強大表示懷疑,你自然是要想辦法來說服我們呀!」
我還沒有開口,小弦子倒是按捺不住了。
「你們兩個……」
見自己的心思被我們看穿,老爹有些無語。
「好吧,那我先給你們演示用指針怎么來實現(xiàn)剛剛的功能:
swap(int* x, int* y)
{
int temp =*x;
*x =*y;
*y = temp;
}
int main(int argc, char const *argv[])
{
int a = 3;
int b = 4;
swap(&a,&b);
}
這樣的話,就能夠實現(xiàn)交換a和b中的值了?!?p> 雖然老爹一幅信誓旦旦的樣子,但我和小弦子剛剛才折戟沉沙,自然會先驗證一遍。一切果然如同老爹所言,a和b中的內容果然變了!那么why?how?
「好了,到這里我們正式進入正題,只有我們將指針的知識講了,你們才會明白這其中的緣由。
剛剛我們說過,指針,其實就是指向一個變量的地址,這里的地址無非就是一個數(shù)字。通常的數(shù)據(jù),如int、double這種,我們都是放在一個變量中,然后使用它們。同樣的,如果我們使用這些地址,也得有相應的數(shù)據(jù)類型類存放,而用來存放地址的變量,就叫做指針變量。
就拿swap函數(shù)的參數(shù)列表來說,int* x其實就是聲明了一個指向int類型的指針變量x。
什么意思呢?這其中其實包含了對內存的讀寫信息。
舉個例子,假設你們班的教室編號是520,因為你們老師教學水平太高了,受到了廣大學生和家長的認可,于是大家都想進入你們班學習。
于是你們班上的學生就越來越多,一個教室已經(jīng)裝不下了,這個時候校長說把521、522、523這三間教室跟你教室打通。
但是這四間教室只有520這個編碼,如果這個時候有人問四年級二班在哪兒,我們就需要告訴人家,520編號的四間教室都是。
同樣,因為不同的數(shù)據(jù)類型占用的內存字節(jié)不同,比如說變量a,它是一個int類型的,那么它在內存中占4個字節(jié)。但是我們獲取它的指針地址時,獲取到的實際上是它的首個字節(jié)的地址,因此我們在使用指針的時候就必須告訴計算機要取幾個字節(jié)。
int*的意思就是一個指向int數(shù)據(jù)類型的指針,這樣聲明計算機就知道,原來使用這個指針地址讀寫數(shù)據(jù)的時候要按照int類型的標準來,也就是要從當前地址開始,操作四個字節(jié)的內存。
同樣的,如果我們聲明一個執(zhí)行double類型的指針變量,就要用double*,以此類推。」