When recursion in C language can omit the thought of return: interpreting the essence of C function return through inline assembly

Source: Internet
Author: User

    • This is the way the blogger uses recursion to write a simple business with C, forgetting to write return due to carelessness. The result is that the returned results are still correct. After half an hour of disassembly, I proved my guess and now share it in my blog. It is also a deepening understanding of C language compiling principle.
    • Introduction:
    • First of all, I would like to take an example of a topic, compare can reflect the problem.
1 : #include <stdio.h> /** function function: Implementing bitwise operations with recursion */ int  Add_recursion (int  a,int  b) {int  carry_num = 0 , add_num = 0 ; if  (b = = 0 ) {return  A; } else  {add_num = a^b; Carry_num = (a&b) <<1 ; Add_recursion (Add_num, carry_num); }}int  Main () {int  num = add_recursion (1 , 1 ); printf ( "%d\n" , num); GetChar ();} 
    • The question is, what is the printed value of the program that is executed as above?
    • You may think that this is a very retarded, even as a small company's pen test is not presentable.

      —————————— – Figure 1 Results of the implementation of Example 1 ———————
    • The answer is 2, no doubt, just a simple recursion.
      But if I change the subject,
Cases2: #include <stdio.h>intChangestack () {return 3;}/** function: Recursive implementation of bit operation addition */intAdd_recursion (intAintb) {intCarry_num =0, Add_num =0;if(b = =0)    {returnA }Else{add_num = a^b; Carry_num = (a&b) <<1;        Add_recursion (Add_num, carry_num);    Changestack (); }}intMain () {intnum = Add_recursion (1,1); printf"%d\n", num); GetChar ();}
    • Let's look at the above procedure, how much will the results be executed?
      There may be many friends who have found the trick carefully.
      There may also be some confusion among some friends, this program simply adds an insignificant function call after the recursive implementation function, and why it affects the result of the function return.
      In fact, printf prints out the incorrect results. Operation result is 3

      —————————-Figure 2 The results of Example 2 ————————-
    • Why does this problem occur, in fact, in the normal case of recursion. When you make a recursive call in the Else statement, you should add a return. Due to the absence of return, the function return value was tampered with by the Changestack () function, thus reading the wrong return value in the main function.
else    {        a^b;        carry_num = (a&b)<<1;        return Add_Recursion(add_num, carry_num);         changestack();    }
  • If the code above is corrected as above, there will be no problem. (Of course, there is no error, at this time with Return,return behind the changestack will not have any chance to execute)
    Now take a step-by-step analysis of the nature of the error.
  • —————— – Figure Three recursive analysis of two functions —————————

  • We analyze the running process of the upper code, first call add_recursion in the main function, the intention is to calculate the value of the values, and pass the function return value to printf print out.
    When a recursive call to the Add_recursion function (add) is computed, the first two recursive calls will jump into the else branch for recursive invocation because they do not meet the recursive egress condition (carry Addend carry_num is 0). The cumulative result is returned until the third recursive call, because Carry_num is 0.

  • The problem is that only the third time the add recursive call is returned, the first and second times when the function returns, there is no return, but returns the call to its own function level after returning the child hierarchy after calling the Changestack () function. When the first-level recursive call is returned to main, Add_recursion does not return, but returns the main function immediately after the execution of the changestack, while the printf of the main function resolves the return value. The return value of Changestack is actually parsed incorrectly. That's why 1+1=3 's error occurred.
  • The reason for all this is that:
    when the function execution finishes returning, the return value is pushed to the stack (in theory, the compiler will actually optimize the return value to the EAX register transition , the VC is the use of eax temporarily saved). When the VC compiler resolves a function return value (integer), the value of EAX is read directly as the return value.

    ———————-Figure Four disassembly analysis of the VC compiler's handling of return ———-
  • According to disassembly analysis can be seen, VC compiler to Changestack () in the return 3 assembly results, that is, MOV eax,3. The return value is actually given to EAX, which is used by the calling function that the EAX register transitions to this function.
  • We can see in the main function the exact procedure for assigning the return value of Changestack () to NUM, which is the memory address where the value of EAX is returned to Num.

    —————————— Figure five function return value of the "stack" rule ——————————-

  • So it's all explained.

——————-Figure Six Example why does the recursive analysis happen correctly —————

    • Although the result of the first question is correct, printf reads the add_recursion return value, not the result of the first recursive call, but the result of the third recursive call to return B (when the third recursive return, the EAX register is temporarily present). And in the subsequent recursive return, the coincidence eax has not been changed. Thus the use of recursion (although not return at the point where return is required) can result in the correct results.
      In fact, we can use an inline assembly code to verify that our guesses are correct. We change the value of the EAX after the recursive call, using the inline assembly plus a code for assembly.

——————————-figure Seven using the inline assembly to interpret the return nature of the C language ————————— –

    • We add a assembler code behind the recursive function add_recursion to change the EAX value at the end of the function. As you can see, in the main function, the function return value is mistaken for the 3 that we set in assembly language. Print out the fallacy of 1+1=3.

    • In fact, the program we're compiling in the example compiles a warning from the C compiler.
      warning C4715: "add_recursion": Not all control paths return values
      A function with a return value, not all the branches will return the value, if you put the blog program on the more strict C + + compiler will be error.

    • This is a very simple case, perhaps we will be lucky to implement functions, but in the case of complex tree or even graph recursion, if you are not sure whether you will be able to get the final result, be sure to return each case is returned value, so as to avoid unexpected program error. The flexibility of the C language should give us the benefit of not providing an unstable element to our program.

When recursion in C language can omit the thought of return: interpreting the essence of C function return through inline assembly

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.