Re: [問題] 函式傳遞的問題

看板C_and_CPP作者 (鬼翼&娃娃魚)時間15年前 (2009/05/22 23:31), 編輯推噓5(503)
留言8則, 5人參與, 最新討論串2/3 (看更多)
※ 引述《hateexam ()》之銘言: : 為什麼這個問題-->見連結例子與其最佳答案 : http://zhidao.baidu.com/question/98153744.html : 必須用call by address才能正確傳遞函式間的結果 : 而以下寫法不用call by address也能正確回傳a[n]的結果呢 小弟不是很喜歡 Call by Address 這個說法, 還是回個文吧.... 為了簡單起見, 這邊就直接代幾個實例來說明這些東西吧.... ==== int a = 10; int b = 20; 上面兩行我定義兩個變數a, b, 變數需要記憶體來存放.... 所以對CPU來說, compile後的程式可能是這種感覺.... 記憶體位址 0x01000000, 這個位址存的數值為 10 記憶體位址 0x01000004, 這個位址存的數值為 20 如果我今天寫個function叫swap()想要交換兩個數.... swap(int n1, int n2) { int temp = n1; n1 = n2; n2 = temp; } main() { .... swap(a, b); .... } 這樣做是不行的, 因為C function只有Call by Value.... 所以swap被呼叫到的時候其實是把a, b的value copy了一份.... 將 0x01000000 裡的 value (10) copy到 0x02000000 裡頭 將 0x01000004 裡的 value (20) copy到 0x02000004 裡頭 因此你swap裡的程式碼最後只會造成下面的結果.... 去取 0x02000000 裡面的 value (10) 放進 temp 去取 0x02000004 裡面的 value (20) 放進 0x02000000 去取 temp 裡的值(10)放進 0x02000004 這個位址 所以swap()執行完以後.... 記憶體位址 0x02000000 在swap()裡最後變成了 20, 但不影響 0x01000000 裡的值 記憶體位址 0x02000004 在swap()裡最後變成了 10, 但不影響 0x01000004 裡的值 ==== 而您查到的網站寫的所謂Call by Address其實是Pass the address of the varible swap(int *p1, int *p2) { int temp = *p1; *p1 = *p2; *p2 = temp; } main() { .... swap(&a, &b); .... } 這樣做可行的是因為, 雖然swap()還是做Call by Value, 但傳入swap()的是address 而swap()接受的參數也不是原先的兩個int, 而是兩個int pointer, 即int* 將 0x01000000 這個 "value" copy到 0x02000000 裡頭 將 0x01000004 這個 "value" copy到 0x02000004 裡頭 在swap()這個function裡現在做得事就比較不一樣.... 去取 0x02000000 裡面的值當位址 (0x01000000) 裡面的 value (10) 放進 temp 去取 0x02000004 裡面的值當位址 (0x01000004) 裡面的 value (20) 放進 0x02000000 裡面的值當位址去 (0x01000000 這個位址) 去取 temp 裡的值(10)放進 0x02000004 裡面的值當位址去 (0x01000004 這個位址) 到這裡 0x01000000 裡面的值就是 20, 0x01000004 裡面的值就是 10, swap成功 ==== 回到您的sort()的問題, 把同樣的address/pointer概念引申一下吧.... int a[5] = {1, 5, 2, 8, 5}; => a[0] 的位址 0x01000000 裡的值為 1, a[1] 的位址 0x01000004 為 5, a[2] 的位址 0x01000008 為 2, 以此類推. sort(int *f1) { /* loop to sort f1[]. */} main() { .... sort(a); .... } sort()的參數f1實際上是把 a (這裡在C語言裡等同於 &a[0], 好像 &a 也是) 0x01000000 這個 "value" copy給f1 (0x02000000) 所以sort()裡對f1[]做讀寫就像swap()裡一樣直接反應在原來a[]的位址裡.... 即 0x01000000, 0x01000004, 0x01000008, 以此類推的這些位址裡.... 所以 sort(a); 與上面的 swap(a, b); 其實是以同樣的概念/原理在運作的:) ==== 以上, 這是小弟的理解, 有漏誤的地方還請大家指正....<(_ _)> 其實temp也會有對應位址, 而且parameter passing也要經過call stack的push/pop 而不是像我上面寫的那麼簡單直接copy; 上面只是簡化一些不是這裡重點的部份 如果能夠畫圖會比較好懂啦, 只是BBS上實在是不會畫Orz 至於C++的Call by Reference, 一種說法是這才是Call by Address 因為如果是用Call by Reference, 那麼swap()的例子就會變為.... swap(int &n1, int &n2) { int temp = n1; n1 = n2; n2 = temp; } main() { .... swap(a, b); .... } 不過小弟我不太會像上面一樣解釋n1, n2, 就留給其他強者補完吧^^|| -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 58.41.5.198

05/23 00:28, , 1F
非常的感謝^^ 雖然我頭腦快打結了...
05/23 00:28, 1F

05/23 00:28, , 2F
非常謝謝大大的用心了
05/23 00:28, 2F

05/25 10:36, , 3F
推好文
05/25 10:36, 3F

09/09 20:25, , 4F
推詳細解說,不過我的腦筋也快打結了。 XD
09/09 20:25, 4F

09/09 20:28, , 5F
對了,文中的varible是少打了一個a嗎?是variable嗎?
09/09 20:28, 5F

09/09 21:02, , 6F
對啦~~凡po過, 必留下錯字....(羞)
09/09 21:02, 6F

09/09 21:02, , 7F
其實, 掛debug trace一次code就會有fu了:)
09/09 21:02, 7F

04/27 16:26, , 8F
好詳細的解說 ^^看了讓我懂了更多 ^^
04/27 16:26, 8F
文章代碼(AID): #1A5iL3A- (C_and_CPP)
文章代碼(AID): #1A5iL3A- (C_and_CPP)