3

In the following code, I wrote a function recursively which should return a value, and really when two numbers are equal it returns, in the function I did not use the return and she is still working, I'd love to get an answer to why it works?

#include <iostream>
#include <string.h>
using namespace std;

int gcd(int num1, int num2);

void main()
{
    int ret_num = gcd(24, 60);
    cout << ret_num << endl;
}

int gcd(int num1, int num2)
{
    if (num1 == num2)
        return num1;
    else
    {
        if (num1 < num2)
            gcd(num1, num2 - num1);
        else
            gcd(num2, num1 - num2);
    }
}
ynon
  • 31
  • 1
  • 2
    That's undefined behavior if this else if reached. However it's likely to work in practice since once you reach the `return num1` then it's just unwinding all the way to the original caller, so the `num1` will probably stay there and get returned. But please fix your code and not rely on any of this. – tux3 Mar 05 '15 at 21:19
  • @tux3 How does `num1` "stay there and get returned" when program's taken the other branch? I'm intrigued, please enlighten me. – LogicStuff Mar 05 '15 at 21:25
  • 3
    @LogicStuff I'll take the example of x86. When you do `return num1` the convention is to put `num1` in `rax` and return. When there is no return value, GCC will probably just return without modifying `rax`, so the `num1` will stay there until we unwind all the way back to the caller. But all of this is highly dependent upon the phase of the moon and may not apply because that's *undefined behavior*. Edit: gcd calls itself on the else branch, so it'll end up either returning or blowing the stack, if that's what you were asking. – tux3 Mar 05 '15 at 21:33
  • @ynon It's an [x86 register](https://en.wikipedia.org/wiki/X86#64-bit) and it's used for many things, notably return values. – tux3 Mar 05 '15 at 21:45
  • 1
    @ynon Something you don't need to care about when you're not writing assembly - the point is that this works by coincidence on your compiler and platform. It might not work on other compilers or platforms. – user253751 Mar 05 '15 at 21:46
  • @immibis If this example works around the windows 7, Visual Studio 2013, I can assume it will always work in this environment? – ynon Mar 06 '15 at 12:16
  • @ynon Compiler options might also affect it, especially optimizations. – user253751 Mar 07 '15 at 02:29
  • Example: (I don't know if MSVC does this, but GCC and clang probably can) Since a function must return a value, the compiler can assume that your `gcd` function always executes a `return` statement. Since the only return statement is `return num1`, it might assume that `return num1` is always executed (and therefore that `num1 == num2`) - and therefore it might optimize the entire function to `int gcd(int num1, int num2) {return num1;}` (or even `return num2`, since they always have to be equal!), and so your code might print 24 (or 60!). – user253751 Mar 07 '15 at 02:34
  • See http://blogs.msdn.com/b/oldnewthing/archive/2014/06/27/10537746.aspx for some more examples of undefined behaviour causing weird optimizations. – user253751 Mar 07 '15 at 02:37
  • Also, note that if you have an EXE file that prints the right answer, you can assume *that EXE file* will always print the right answer, since this is a compile-time thing and not a run-time one. – user253751 Mar 07 '15 at 02:38

0 Answers0