作者LPH66 (運命のルーレット廻して)
看板b94902xxx
標題[心得] 有關return
時間Mon Oct 17 23:10:34 2005
幫了幾個求助之後,
發現大家的一個大問題是:
到底return會回到哪裡去?
我們先用一個簡單的函數呼叫的例子來看好了:
void a(int x);
int b(int y);
int main(void)
{
int c;
a(5);
/*[A]*/
printf("a returns %d\n",c);
return 0;
}
void a(int x)
{
int d;
printf("%d + %d = %d\n",x,x,x+x);
d=b(x);
/*[B]*/
printf("b returns %d\n",d);
return;
}
int b(int y)
{
printf("%d * %d = %d\n",y,y,y*y);
return y+5;
}
好,我們在main呼叫了a(5);
然後a裡面呼叫了b(x);
然後b做完,return了一個值,
請問b的return會回到哪裡?
1. main的開始
2. a的開始
3. b的開始
4. 標[A]的地方
5. 標[B]的地方
6. 以上皆非
.
.
.
.
答案是5. 標[B]的地方。
所謂return, 就是回到
呼叫自己的那個人的地方,
也就是說
剛剛誰呼叫我,現在我做完了,換你繼續。
因此,在上面這個例子中,呼叫b()的是標[B]的地方那個人(就是a),
於是這裡的return就回到那邊去。
同理,a()的return所回到的地方,就是叫a()的那個人,也就是標[A]的地方。
那這裡a它return給main什麼呢? 一個訊息: a我已經做完了,你可以繼續做。
現在來看遞迴呼叫的情形:
int main(void)
{
int s;
s=sum(5);
/*[C]*/
printf("sum of 1 to 5 is %d.\n",d);
return 0;
}
int sum(int x)
{
if(x==1)
return 1;
else
return x+sum(x-1);
/*[D]*/
}
在這個情形中,sum自己呼叫自己,
所以有人就搞混了: 到底sum的return會回到哪裡去?
是回到[C]? 還是回到[D]?
答案是: 要看是誰叫他們的。
在上面的例子中,main在[C]的地方先呼叫了一個sum(5),
於是sum就跳了一個分身出來叫sum(5),來處理main的呼叫。
然後sum(5)看到要他算5+sum(4),所以在[D]的地方呼叫了sum(4),
這個時候sum又跳了一個分身出來叫sum(4),來處理sum(5)的呼叫。
然後sum(4)看到要算4+sum(3),又呼叫了sum(3),
所以sum又跳了sum(3)這個分身出來,
sum(3)要算3+sum(2),呼叫sum(2),sum跳出sum(2)分身,
sum(2)要算2+sum(1),呼叫sum(1),sum再跳出sum(1)分身,
最後sum(1)看到自己要算的是1,這他可以算,
然後他要把這個值return回去。return給誰呢?
sum(1)看一看是誰叫他的。是sum(2),所以他把這個值給了sum(2)。
sum(2)看到他要的sum(1)已經算好給他了(是1),
於是他就算他的2+sum(1)=2+1=3。
算好了要return,return給誰? sum(2)看誰叫他的。是sum(3),所以他把3給了sum(3)。
就這樣一直算,一直return,到最後sum(5)終於完成了他的任務,算出答案(15),
然後他也要return,這次他看到是main叫他的,所以他把15給了main。
main得到答案15 就高興的printf出來: sum of 1 to 5 is 15.
這樣子各位有比較了解return到底回到哪裡去了嗎?
使徒四的密技中,助教這樣寫:
: if (不是數字0) {
: 往下試;
: } else {
: 記錄已經被使用過的數字(行, 列, local九宮格);
: for each available number i do
: {
: 填 i;
: 往下試;
: 填回 0;
: }
: }
這所謂的"往下試",其實就是叫另一個分身出來去試著填下一個位置。
那分身要怎麼告訴你後面是有路還是沒路呢?
這就是分身的return。
如果我們這樣設定: 只要我找到答案了,直接印答案之後結束程式,
那我們在函數最後(確定此後沒路了)寫上return;
那麼當分身試完,發現沒路了,
他就會告訴上一個分身: "我這裡已經確定沒路了,你可以繼續試下一個",
叫人的分身知道了後面沒路,自己就換一下填的數字,再叫那個分身出來試試看。
如果在後面分身處理沒路時,你又叫了一個分身出來,告訴他處理前面,
新叫的分身可不會知道原來的分身做了什麼,他會重頭開始做,
所以就會一直呼叫呼叫……,
到最後查克拉(stack)不夠就會累掛了(stack overflow)。
這樣有比較清楚要怎麼做了嗎?
--
"LPH" is for "Let Program Heal us"....
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.240.54
推 alex1025:雖然我是雙班的~你寫的很清晰易懂~連我這個弱者都看的懂. 10/17 23:14
推 NeantD:推 10/17 23:24
→ yjpetergto:推..這個問題困擾了我好久...謝謝 10/17 23:26
推 frankfbo:看了怎可不推~ 10/17 23:48
推 IamrealBB:恩,有看有推XD 10/17 23:55
推 sa033766:高手 推 10/17 23:55
※ 編輯: LPH66 來自: 140.112.240.54 (10/18 00:03)
→ LPH66:囧 我發現我忘了加還原碼 已經加上去了 10/18 00:03
推 SadCrusader:推~~~~~ 10/18 00:21
推 hamigwa:GooooooooooooooooooooooooD 10/18 00:44
推 springgod:提醒一下萬一分了兩次sum(4)出來 他們還是不一樣的喔:) 10/18 10:18
→ springgod:詳情可以上p老師的ACP-DP會教怎麼運用更強大的影分身XD 10/18 10:19
推 anauma:推~~強者風範! 謝謝指導 10/18 10:25
推 pangfeng:可以轉到Sandbox嗎? 10/19 19:12