1. 程式人生 > >【遞歸】執行過程探究(c)

【遞歸】執行過程探究(c)

ase 部分 函數賦值 自己的 cto tdi tro 地方 inpu

c語言 遞歸的執行過程探究

引用《c primer plus》第五版 9.3.1 遞歸的使用

 1 /* recur.c -- recursion illustration */
 2 #include <stdio.h>
 3 void up_and_down(int);
 4 
 5 int main(void)
 6 {
 7     up_and_down(1);
 8     return 0;
 9 }
10 
11 void up_and_down(int n)
12 {
13     printf("Level %d: n location %p\n", n, &n); /*
1 */ 14 if (n < 4) 15 up_and_down(n+1);             /* 遞歸處 */   16 printf("LEVEL %d: n location %p\n", n, &n); /* 2 */ 17 18 }

過程:  main()調用了up_and_down(1),
然後第一層的up_and_down(此時i為1),
執行到了我註釋的那個地方/*遞歸處*/即第15行
在遞歸處調用了up_and_down(調用時將1+1賦給了第二層的參量i)

由於調用後執行還沒有完成,所以還輪不到/* 2 */ 處的打印,
第二層的up_and_down又執行到了/*遞歸處*/
,以此類推。


最後執行到了最深層時,n不再滿足小於4的條件,所以不再遞歸。
就執行了/* 2 */ 處的打印,然後函數結束了,就return返回值【此處return void;】並退出當前層的函數
次深層檢測到 被自己調用的函數的返回值 後繼續執行/* 2 */ 處的打印,結束後再return void; 依次類推。
 

輸出結果為:

LEVEL 1: n location 0x0012ff48
LEVEL 2: n location 0x0012ff3c
LEVEL 3: n location 0x0012ff30
LEVEL 4: n location 0x0012ff24
LEVEL 4: n location 0x0012ff24
LEVEL 3: n location 0x0012ff30
LEVEL 2: n location 0x0012ff3c
LEVEL 1: n location 0x0012ff48





總結:由於c語言的順序結構,所以調用函數後要等待被調用的函數執行完成(即有返回值後)才能執行下一步,而遞歸恰恰是一層一層地調用自己,所以得等到最深層執行完成後,才返回值告訴次深層函數可以繼續執行。次深層執行後才能返回告訴次次深層繼續執行。
【在函數沒有執行完成前,不return。 導致了每一個函數都得等待被調用函數的返回才能繼續,不斷調用就得不斷等待被調用的函數,因此必須等最深層函數開始返回後才有了一步步的函數的後續執行和返回】


重點:調用時的LEVEL1地址和返回時的LEVEL1(LEVEL數字)是相同的
每一級遞歸都使用自己的私有變量(子函數中變量的作用域和儲存時期部分的知識)








關於利用遞歸函數賦值的部分,引用《c primer plus》第五版 9.3.3尾遞歸
 1 // factor.c -- uses loops and recursion to calculate factorials
 2 #include <stdio.h>
 3 long fact(int n);
 4 long rfact(int n);
 5 int main(void)
 6 {
 7     int num;
 8 
 9     printf("This program calculates factorials.\n");
10     printf("Enter a value in the range 0-12 (q to quit):\n");
11     while (scanf("%d", &num) == 1)
12     {
13         if (num < 0)
14             printf("No negative numbers, please.\n");
15         else if (num > 12)
16             printf("Keep input under 13.\n");
17         else
18         {
19             printf("loop: %d factorial = %ld\n", 
20                     num, fact(num));
21             printf("recursion: %d factorial = %ld\n", 
22                     num, rfact(num));
23         }
24         printf("Enter a value in the range 0-12 (q to quit):\n");
25     }
26     printf("Bye.\n");
27   
28     return 0;
29 }
30 
31 long fact(int n)     // loop-based function
32 {
33     long ans;
34 
35     for (ans = 1; n > 1; n--)
36         ans *= n;
37     
38     return ans;
39 }
40 
41 long rfact(int n)    // recursive version
42 {
43     long ans;
44 
45     if (n > 0)
46         ans= n * rfact(n-1);
47     else
48         ans = 1;
49   
50     return ans;
51 }

首先,此處的賦值是 將 函數返回值 賦給一個變量

所以遞歸賦值這種也是一樣的:
一步步等待,直到最深層函數執行完成並返回後
次深層才能利用返回值執行賦值操作,然後再執行完成並返回
次次深層才能利用返回值執行賦值操作......
依次類推




=========End

【遞歸】執行過程探究(c)