程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 用匯編的眼光看C++(之退出流程)

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

編輯:C++入門知識

 

【 聲明:版權所有,歡迎轉載,請勿用於商業用途。  聯系信箱:feixiaoxing @163.com】

 

 

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

 

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

 

 

21:       for(int m = 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:       { 

23:           if(m / 20 == 3) 

00401650   mov         eax,dword ptr [ebp-4] 

00401653   cdq 

00401654   mov         ecx,14h 

00401659   idiv        eax,ecx 

0040165B   cmp         eax,3 

0040165E   jne         process+42h (00401662) 

24:           { 

25:               break; 

00401660   jmp         process+55h (00401675) 

26:           } 

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:           { 

30:               continue; 

00401671   jmp         process+21h (00401641) 

31:           } 

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一般用的情況不多,但是有一種情況例外?

 

 

void  process() 

    if(/* get resources one */ == 0) 

    { 

        return; 

    } 

 

    if(/* get resource two  */ == 0) 

    { 

        /* free resource one */ 

        return; 

    } 

 

    if(/* get resource three */ == 0) 

    { 

        /* free resource two */ 

        /* free resource one */ 

        return; 

    } 

 

    if(/* get resource four */ == 0) 

    { 

        /* free resource three */ 

        /* free resource two */ 

        /* free resource one */ 

        return; 

    } 

 

    /* ... */ 

 

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

 

void  process() 

    if(/* get resources one */ == 0) 

    { 

        return; 

    } 

 

    if(/* get resource two  */ == 0) 

    { 

         

        goto fail_one; 

    } 

 

    if(/* get resource three */ == 0) 

    { 

        goto fail_two; 

    } 

 

    if(/* get resource four */ == 0) 

    { 

         

        goto fail_three; 

    } 

 

    /* ... */ 

fail_three: 

    /* free resource three */ 

 

fail_two: 

    /* free resource two */ 

 

fail_one: 

    /* free resource one */ 

    return; 

    (3)return也是跳出代碼段一個很好的方法。

 

    它不光可以在函數中使用,也可以靈活運用在循環語句、判斷語句中。要是在遞歸語句中,更是少不了他的身影。比如說,我們現在查看一個字符串是否滿足這樣一個結構:

 

    str = ab | a str b;

 

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

 

 

BOOL process_multi_char(const char* str, int length) 

    if(2 == length) 

        return !strncmp(str, "ab", strlen("ab")) ? TRUE : FALSE; 

 

    if(str[0] == 'a' && str[length -1] == 'b') 

        return process_multi_char(str+1, length-2); 

    else 

        return FALSE; 

 

BOOL process(const char str[], int length) 

    if(NULL == str ||  length < 2 || (0 != length % 2)) 

        return FALSE; 

 

    return process_multi_char(&str[0], length); 

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved