用彙編的眼光看C (之退出流程)

2021-06-02 16:37:41 字數 2961 閱讀 7120

無論是在判斷還是在迴圈的過程中,通常在遇到合適的條件的時候就會退出相應的模組。跳出模組執行的方式很多,break,continue,return都可以。下面我們就可以分別對他們進行將介紹。

(1)continue只能用於迴圈,而break迴圈、判斷都可以應用。兩者有什麼區別呢?

view plain

21:       

for(

intm = 10; m < 100;  m ++)  

00401638   mov         dword ptr [ebp-4],0ah  

0040163f   jmp         process+2ah (0040164a)  

00401641   mov         eax,dword ptr [ebp-4]  

00401644   add         eax,1  

00401647   mov         dword ptr [ebp-4],eax  

0040164a   cmp         dword ptr [ebp-4],64h  

0040164e   jge         process+55h (00401675)  

22:         

27:  

28:           if

(m / 10 == 0)  

00401662   mov         eax,dword ptr [ebp-4]  

00401665   cdq  

00401666   mov         ecx,0ah  

0040166b   idiv        eax,ecx  

0040166d   test        eax,eax  

0040166f   jne         process+53h (00401673)  

29:             

32:       }  

00401673   jmp         process+21h (00401641)  

我們在迴圈模組裡面可以看到了**做了兩次判斷。一次判斷是檢視m除以20是否等於3,一次判斷是檢視m除以10是否可以整除。同樣,前面的判斷結果是break,後面的結果是continue,那麼兩者之間的區別是什麼呢?我們可以好好看一下。在第一次條件判斷的時候,我們發現如果m除以20不等於3,那麼下面指令直接跳轉到0x00401662,也就是第二條件的入口處。但是如果第乙個條件判斷成功了,那麼程式就會跳轉到位址0x00401675,也就是說整個迴圈模組已經結束了。而continue呢?我們發現不管條件判斷是否為真,那麼指令都會跳轉到0x00401641處執行,也就是迴圈+1的地方。這說明continue結束的只是本次迴圈,整個迴圈的流程還沒有結束,而break表示當前已經推出了整個迴圈模組。如果大家對書本上的概念還有些模糊的話,那麼彙編指令在這裡已經把細節之處解釋得明明白白了。

(2)goto一般用的情況不多,但是有一種情況例外?

view plain

void

process()  

if(/* get resource two  */

== 0)  

if(/* get resource three */

== 0)  

if(/* get resource four */

== 0)  

/* ... */

}  

通常情況下,我們建立乙個物件時,需要各種各樣的資源,等到所有資源都分配齊了,我們的**才能開始工作。但是事實上,也存在很多分配失敗的可能性。如果遇到了分配失敗,那麼我們就要對原來的資源進行釋放處理。隨著資源的總數越來越多,這個**塊就會顯得越來越臃腫。那麼有沒有什麼好的辦法解決這一難題呢?goto就是一種好的選擇。

view plain

void

process()  

if(/* get resource two  */

== 0)  

if(/* get resource three */

== 0)  

if(/* get resource four */

== 0)  

/* ... */

fail_three:  

/* free resource three */

fail_two:  

/* free resource two */

fail_one:  

/* free resource one */

return

;  }  

(3) return也是跳出**段乙個很好的方法。

它不光可以在函式中使用,也可以靈活運用在迴圈語句、判斷語句中。要是在遞迴語句中,更是少不了他的身影。比如說,我們現在檢視乙個字串是否滿足這樣乙個結構:

str = ab | a str b;

那麼換成函式**應該怎麼編寫呢?大家可以自己先試一試,下面是我的乙個方法:

view plain

bool

process_multi_char(

const

char

* str, 

intlength)  

bool

process(

const

char

str, 

intlength)    

這裡return的好處就是充分把字串進行了拆分。我們按照定義,先從基本的問題下手,大事化小,小事化了。當然這裡的小事就是字串這有兩個字元的情形,也是最底層函式的出口。要不然函式就會一致不停地處理下去,這是沒有意義的。計算過程中一旦發現了不合法的運算,那麼整個迭代的過程就會結束,快速回溯,輸出結果。所以說要想寫好遞迴或者是用到堆疊結構的**時,必須考慮**的入口和出口的把握,而return就是最好的選擇,什麼時候return,什麼時候迭代都要把握時機,否則很容易陷入到死迴圈當中去。

用彙編的眼光看C (之退出流程)

無論是在判斷還是在迴圈的過程中,通常在遇到合適的條件的時候就會退出相應的模組。跳出模組執行的方式很多,break,continue,return都可以。下面我們就可以分別對他們進行將介紹。1 continue只能用於迴圈,而break迴圈 判斷都可以應用。兩者有什麼區別呢?21 for int m ...

用彙編的眼光看C (之退出流程)

無論是在判斷還是在迴圈的過程中,通常在遇到合適的條件的時候就會退出相應的模組。跳出模組執行的方式很多,break,continue,return都可以。下面我們就可以分別對他們進行將介紹。1 continue只能用於迴圈,而break迴圈 判斷都可以應用。兩者有什麼區別呢?cpp view plai...

用彙編的眼光看C (之退出流程)

無論是在判斷還是在迴圈的過程中,通常在遇到合適的條件的時候就會退出相應的模組。跳出模組執行的方式很多,break,continue,return都可以。下面我們就可以分別對他們進行將介紹。1 continue只能用於迴圈,而break迴圈 判斷都可以應用。兩者有什麼區別呢?cpp view plai...