C語言再學習4 迴圈 為什麼盡量避免遞迴

2021-08-28 09:59:18 字數 3727 閱讀 8131

for (int i=0;i<5;i++)

//如果變數i小於5,就一直執行,每次執行一次然後變數i自己加1

乙個for迴圈就這麼簡單, 可是為什麼i能控制這個迴圈的次數?我們應該反過來學習:

for (int i = 0; i < 5; i++)
這是乙個空的for迴圈,讓我們來看看

mov         dword ptr [ebp-8],0          //這行應該就是我們的int i=0了
00d417b6 eb 09                jmp         main+31h (0d417c1h)  

緊接著就直接跳轉到了

cmp dword ptr [ebp-8],5 //0d417c1h

然後乙個jcc,jge,讓我們來複習一下jge是什麼?
jge大於等於則跳轉(有符號數)

sf=of

結論:迴圈控制條件變數i存在ebp-8的位置,把0放到ebp-8以後(int i=0),jmp到(i是否大於等於5),如果i大於等於5,就跳出迴圈,if(i>),由於在彙編中用大於等於就跳出來表示小於5則繼續執行,所以ebp-8(變數i)並沒有小於5,則繼續執行,然後jmp回i++,變數i加完以後繼續執行比較,由次重複

跳轉到這行語句以後,拿著5和ebp-8來比較,這裡證明我們上面的猜想是正確的,ebp-8存了我們的變數i

可見ebp-4這個位址並沒有使用,那我們能不能把ebp-4當成乙個引數的入口來使用呢?ebp-8等於1,是因為我的if語句控制在,當變數i等於1的時候才執行這些彙編語句(為了值執行一次)

簡單描述一下這個**的作用:

當我們通過實驗得出結論,for迴圈的第乙個引數是自身的控制迴圈用的變數,而這個變數存在ebp-8

int i;

while (i<5)

//我常使用的方式

讓我們先來看看反彙編,for迴圈如此強大, 為什麼還要while迴圈?

int i=0;

000517b8 c7 45 f8 00 00 00 00 mov dword ptr [i],0

while (i<5)

000517bf 83 7d f8 05 cmp dword ptr [i],5

000517c3 7d 0b jge main+40h (0517d0h)

。。。

定義乙個變數i,把變數i和控制迴圈次數5比較,通過jcc中的jge來判斷跳轉

兩個迴圈的區別:讓我們先看看為什麼需要兩個不同的迴圈?

for迴圈:也稱為計數迴圈,通過次數來控制

while迴圈:也稱條件迴圈,通過條件來迴圈

可見兩個迴圈,都是通過jge來比較和跳轉,唯一不同的是,for迴圈使用堆疊,ebp-8來儲存變數,並且控制迴圈。

而while迴圈使用區域性變數或者全域性變數來控制迴圈,這個變數可以是布林值也可以是數字

do…while迴圈

先執行一次條件語句再進行迴圈

do...while迴圈與while迴圈並沒有什麼本質區別,就是在流程方面不太一樣而已!

do...while是先執行功能**,再判斷是否合理,而while是先判斷是否合理再執行功能

遞迴

遞迴通俗來講就是不停的呼叫自身,直到迴圈條件結束

int func(int n)

int main()

讓我們來看看反彙編

00ee420f c7 45 f8 05 00 00 00 mov         dword ptr [n],5  

int n = 5;

printf("n! = %d\n", func(n));

00ee4216 8b 45 f8 mov eax,dword ptr [n]

00ee4219 50 push eax

00ee421a e8 74 d1 ff ff call func (0ee1393h)

00ee421f 83 c4 04 add esp,4

00ee4222 50 push eax

00ee4223 68 cc 7b ee 00 push offset string "n! = %d\n" (0ee7bcch)

00ee4228 e8 4d d1 ff ff call _printf (0ee137ah)

00ee422d 83 c4 08 add esp,8

int func(int n)

00ee25aa 5f pop edi

00ee25ab 5e pop esi

00ee25ac 5b pop ebx

00ee25ad 81 c4 c0 00 00 00 add esp,0c0h

00ee25b3 3b ec cmp ebp,esp

00ee25b5 e8 58 ec ff ff call __rtc_checkesp (0ee1212h)

00ee25ba 8b e5 mov esp,ebp

00ee25bc 5d pop ebp

00ee25bd c3 ret

這是我們的遞迴函式

我們發現在

00ee259e e8 f0 ed ff ff       call        func (0ee1393h)
這個位置,又呼叫了自身函式,一直呼叫。最後總結:

執行過程:

-》func(5)

-》5func(4)

-》5(4func(3))

-》5(4*(3func(2))))

-》5(4*(3*(2*func(1))))

當n為0的時候停止遞迴,返回結果

由於遇到1的時候返回1,那麼func(1)=1

所以結果是5*(4*(3*(2*1))) = 120

c語言學習 4 迴圈

一 for和while等價替換 inti 1 for i i 100 i inti 1 while i 100 二 從鍵盤輸入乙個數字,如果該數字是回文數,則返回yes,否則返回no 回文數 正著寫倒著寫一樣的數 include intmain if sum val else return 0 三 ...

C語言學習筆記 4 之迴圈結構

介紹 迴圈本質上就是重複,所有需要重複執行的 都可以用迴圈來實現。在c語言中,能夠達到迴圈效果的語句有如下 1 if和goto語句構成的迴圈 2 while語句 3 for語句 4 do while語句 goto語句 goto語句是無條件跳轉語句,讓cpu到指定的地方去執行。語法 goto 行標識 ...

C語言學習篇 32 為什麼C語言不能函式過載

在日常的開發中,我們有時會遇到根據不同情景,想通過傳入不同型別的引數,而呼叫統一的函式介面,即函式過載。在c 中原生支援了函式過載,而在c語言中並不支援,只能通過一些技巧來變相解決,如定義flag形參,根據flag值不同,進行不同的處理。例如 void test void a,void b,int ...