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 because of carelessness. The result is that the returned results are still correct. After half an hour of disassembly debugging. proved my guess, and now I 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, the comparison 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 problem is. What is the printed value of the program that runs 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 operation of Example 1 ———————

    • The answer is 2, no doubt, just a simple recursion.


      But suppose 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. What will be the result of the operation?
      There may be a lot of friends who have been careful to find the fishy.


      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 wrong results. Operation result is 3

      —————————-Figure 2 The results of the example 2 run ————————-

    • Why this problem arises. In fact, the recursion is normally the case.

      When a recursive call is made in the Else statement. A return should be added.

      Due to the absence of return, the function return value is tampered with by the Changestack () function. The return value of the error is read in the main function.

else    {        a^b;        carry_num = (a&b)<<1;        return Add_Recursion(add_num, carry_num);         changestack();    }
  • Assuming that the code above is corrected as above, there will be no problem.

    (Of course, there is no error, at this time with the return,return behind the Changestack will not have any opportunity to run at all)
    Now take a step-by-step analysis of the nature of the mistakes that occurred.

  • —————— – 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 plus, and pass the function return value to printf print out.


    In the recursive call to the Add_recursion function (add), the first two recursive calls because the recursive egress condition is not met (Carry Addend carry_num is 0). Jumps into the Else branch for recursive invocation.

    Until the third recursive call because Carry_num is 0. This returns the cumulative result.

  • 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 instead returns the main function immediately after running Changestack, and when printf of the main function parses 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 runs at the end of return. Will stack the return value (theoretically, the compiler will actually optimize the return value to the EAX register transition .) VC is the use of eax temporary Save). 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 see, 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 a detailed 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. It is not the result of the first recursive call, but the result of the third recursive call to return B (the EAX register is temporarily present in the third recursive return). And in the subsequent recursive return, the coincidence eax has not been changed.

      Thus the use of recursion (although not return at the place 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. Can see. In the main function, the function return value mistakenly think we set in assembly language 3. 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 of the branches will return the value, assuming that the blog program in the more stringent C + + compiler will be error.

    • This is just a very easy case. Maybe we'll be lucky. To implement functions, but in the case of complex tree-like or even graph recursion, assuming that you are not sure whether you will be able to get the results, be sure to return each case to the returned value, so as to avoid an 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.