7

I was writing something similar to the code below and I accidentally called the same function inside the body of the function definition.

double function(double &value)
{
     //do something with a here
     if(some condition)
     {
           function(a);
     }
     return a;
}

Consider something of the form:

int function(int &m)   {
    m = 2*m;
    if(m < 20)
    {
        function(m);
    }
    return m;
};

int main()  {
    int a = 2;
    std::cout <<"Now a = "<<function(a);
    return 1;
}

According to me this should not run let alone compile. But it does run and gives out the correct result

Now a = 32

I have called the function before I even 'finished' defining it. Yet, it works. Why?

Lstor
  • 2,265
  • 17
  • 25
Colorless Photon
  • 399
  • 1
  • 3
  • 19

2 Answers2

14

A function calling itself is known as a recursive function. This works because the compiler only needs the declaration of a function, not its definition, for you to be able to call it. The first line of the definition also serves as a declaration. (For details, see § 8.4.1.2 of the C++11 standard.)

Recursion is well-suited to solve many problems. The typical example of a recursive function is the factorial function. It is defined as factorial(n) = n * factorial(n-1).

You can try running this piece of code to get a bit more understanding of what happens when a function calls itself:

#include <iostream>

int factorial(unsigned int n)
{
    std::cout << "Computing factorial of " << n << "\n";

    int result;
    if (n == 0) {
        result = 1;
    } else {
        result = n * factorial(n-1);
    }

    std::cout << "factorial(" << n << ") = " << result << "\n";
    return result;
}

int main()
{
    factorial(5);
}

For more information about declaration vs. definition, see this answer. The Wikipedia page about the One Definition Rule might also be helpful.

Community
  • 1
  • 1
Lstor
  • 2,265
  • 17
  • 25
  • 3
    I would like to add that in general you should prefer using iteration to using recursion. So if you'd like to calculate factorial, you'd better use `int result; for (int i=2; i<=n; ++i) result *= i;`, because 1) it works faster, since calling a function is not free; 2) If you went too deep into recursion, you would probably get (ha-ha) a stack overflow :) Recursion is a very powerful tool, and many algorithms are pointless without it. But use it with caution. – FreeNickname Jun 30 '13 at 07:03
4

It's because you misunderstand what "defining" a function means.

First of all let's get the semantics correct: In order to refer to a function you just need its declaration and not its complete implementation.

Typically, there are two steps in creating an executable: 1) Compiling and 2) Linking.

Compiling

The compiling step works out that the syntax of each piece is okay for each function. In order to compile you need the core language keywords or properly declared symbols. The compiler puts these together but does not resolve whether or not those symbols actually point to real objects in the executable. An object is either bits of data, or bits of instruction. Usually these blobs are called data-segments and text-segments in an object file.

Linking

It's in the linking step that each of the blobs, which is still identified using symbols is put together to see if all the references in the code have corresponding blobs.

Self-reference

Now that you know that all you need to evaluate whether or not syntax is correct (compilation step) is the declaration. The fact that you have a symbol reference within the body of the function itself is not a problem at all.

What you are doing above is short-hand for the following:

int function(int &m); // implicit declaration 

int function(int &m) {
    m = 2*m;
    if(m < 20)
    {
        function(m); // this only requires the declaration to be accepted 
                     // by the compiler. 
    }
    return m;
};

int main()  {
    int a = 2;
    std::cout <<"Now a = "<<function(a);
    return 1;
}

This ability is very important because it's fundamental to creating recursive functions. Some problems can be solved with recursion a lot more elegantly than with iterations, especially when you start throwing in n-way recursive functions.

Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58
  • 1
    Why are you saying he misunderstands what defining a function means? – Lstor Jun 30 '13 at 06:25
  • 1
    Let me clarify, defining a function in C/C++ is usually taken to be just declaring it. It does not involve actually providing the implementation of the function. However, normal english usage would be defining the body. The ambiguity creates the misunderstanding. Actually because of `#defines` the word shouldn't really even be used in C/C++ language-proper context but rather the use should be limited to the pre-processor context. – Ahmed Masud Jun 30 '13 at 06:31
  • That is simply not correct. The C++ standard and normal C++ terminology clearly separates between declaring and defining a function, and those definitions correspond with OP's usage. I recommend that you read §§ **8.3.5** and **8.4** of the standard. – Lstor Jun 30 '13 at 06:43
  • @Lstor do you think that he understands that defining a function declares it implicitly? – Ahmed Masud Jun 30 '13 at 06:44
  • @AhmedMasud No I do not. Care to clarify? – Colorless Photon Jun 30 '13 at 06:46
  • 2
    @ColorlessPhoton See http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration for a further explanation of declaration vs. definition. Like I pointed out in my answer, the first line in the definition is also a declaration. The Wikipedia page about the *One Definition Rule* is also relevant. http://en.wikipedia.org/wiki/One_Definition_Rule – Lstor Jun 30 '13 at 06:49