[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]
Whether in the Process of judgment or loop, the corresponding module is usually exited when appropriate conditions are met. There are many ways to exit the module, such as break, continue, and return. Next we will introduce them separately.
(1) Continue can only be used for loops, while break loops and judgments can all be applied. What is the difference between the two?
21: for(int m = 10; m < 100; m ++)00401638 mov dword ptr [ebp-4],0Ah0040163F jmp process+2Ah (0040164a)00401641 mov eax,dword ptr [ebp-4]00401644 add eax,100401647 mov dword ptr [ebp-4],eax0040164A cmp dword ptr [ebp-4],64h0040164E jge process+55h (00401675)22: {23: if(m / 20 == 3)00401650 mov eax,dword ptr [ebp-4]00401653 cdq00401654 mov ecx,14h00401659 idiv eax,ecx0040165B cmp eax,30040165E 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 cdq00401666 mov ecx,0Ah0040166B idiv eax,ecx0040166D test eax,eax0040166F jne process+53h (00401673)29: {30: continue;00401671 jmp process+21h (00401641)31: }32: }00401673 jmp process+21h (00401641)
We can see in the loop module that the Code has made two judgments. One judgment is to check whether M is divided by 20 is equal to 3, and one judgment is to check whether M is divided by 10 can be divided. Similarly, the previous judgment result is break and the subsequent result is continue. What is the difference between the two? Let's take a look. In the first condition judgment, we found that if M is divided by 20 and not equal to 3, the following command directly jumps to 0x00401662, that is, the entrance to the second condition. However, if the first condition is determined successfully, the program will jump to address 0x00401675, that is, the entire loop module has ended. What about continue? We found that no matter whether the condition is true or not, the command will jump to 0x00401641 for execution, that is, the place where the loop is + 1. This indicates that the end of continue is only this cycle, and the entire cycle process is not over yet. Break indicates that the entire loop module has been launched. If you are still vague about the concepts in books, the compilation commands have clearly explained the details here.
(2) does a goto generally work in a few cases, but is there an exception?
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;}/* ... */}
Generally, when we create an object, we need various resources. After all resources are allocated, our code can start to work. But in fact, there are also many possibilities of allocation failure. If the allocation fails, we need to release the original resource. As the total number of resources increases, this code block will become increasingly bloated. Is there any good way to solve this problem? Goto is a good choice.
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 is also a good way to jump out of the code segment.
It can be used not only in functions, but also in loop statements and judgment statements. It is even more indispensable in recursive statements. For example, we can check whether a string meets the following structure:
STR = AB | a str B;
So how should I write the function code? You can try it first. Here is one of my methods:
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);elsereturn 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);}
Here, the benefit of return is that the string is fully split. According to our definition, we should start with the basic problems, and make things easier and easier. Of course, the trivial thing here is that the string has two characters, which is also the exit of the underlying function. Otherwise, the function will be processed continuously, which is meaningless. Once an illegal operation is found in the calculation process, the entire iteration process ends, quickly backtracing, and outputs results. Therefore, to write code that is recursive or that uses a stack structure, you must consider the entry and exit of the Code. Return is the best choice. When is return, the timing of iteration should be grasped; otherwise, it is easy to fall into an endless loop.
[Notice: The following blog is an embedded assembly of C ++ from the perspective of compilation]