Function Calls

Note: Function calls are going to be introduced in the fifth week of the course.

In C++, one of the constructs for structuring code is functions. For example, we can define a function that finds a larger of two integers as follows:

int max(int a, int b) {
  if (a > b) {
    return a;
  } else {
    return b;
  }
}

The int max(int a, int b) is called the function signature. The word before the parenthesis (max)is the function name. int before the function name is the function return type. Between the parenthesis we have a declaration of function parameters, in this case, the function has two parameters of type int: a and b. After we declared the function, we can call it to compute the result for us. For example, in the following main function we call function max with arguments x and y:

#include<iostream>
int max(int a, int b) { /* code from above */ }
int main() {
  int x = 4;
  int y = 8;
  int larger;
  larger = max(x, y);
  std::cout << larger << std::endl;
  return 0;
}

We can trace this program as follows:

  1. We create a table as before, just now we additionally write the function signature with argument names omitted as the title of the table. For main, the initial table would look like this:

    table 1

  2. We execute the first statement int x = 4; as before and get the following table:

    table 2

  3. Similarly for the second int y = 8; and third int larger; statements. The table we have so far is:

    table 3

  4. Now, the next statement is larger = max(x, y); that is composed of a function call max(x, y) and assignment of the function result to the variable larger. First, we execute the function call. We do that as follows:

    1. We create a new table for the target function max:

      table 4.1

    2. Then, we create a local variable for each parameter of the function max:

      table 4.2

    3. Then, we evaluate the arguments passed to the function and match them with the newly allocated variables. For example, the first argument to the function max is x, which evaluates to 4. Since the first parameter is a, we write 4 as the value of a. Similarly, we compute the value of b and the updated table looks like this:

      table 4.3

    4. Once we initialized all the parameters, we continue tracing the program as before, just now we use the newly allocated table.

    5. To decide which branch we need to take, we need to evaluate the expression a > b. We lookup the values of a and b in the latest table and then evaluate the expression. Since 4 > 8 is false, we take the else branch.

    6. The statement on the else branch is return b;. We evaluate the expression b and write the computed value next to the function signature. Then, we cross out the table for the call of the max function and return back to evaluating in the main function.

      • Note: if the function return type is void (that is, the function does not return anything), we omit the computation of its return value.
      • Note: if we reach end of the non-void function body without executing the return statement, that indicates the we found a bug in our program and we have to stop tracing. The updated tables look as follows:

      table 4.6

    7. To finish evaluating statement larger = max(x, y);, we still need to assign the function result to variable larger. We do it as before. Both tables now look like this:

      table 4.7

  5. The next statement in our main function is std::cout << larger << std::endl;. We execute it as usual and get the following output:

    Program Output
    8
  6. The final statement of the program is return 0;. We execute it in the same way as the previous return statement: we write 0 next to the function signature and cross out the table. Since this was the last table, the program terminates. The final state looks as follows:

    table 6

Note: C++ Tutor does support function calls, so you can use it to check your traces.

Exercises

Task 1 What values are going to be printed by the following program:

#include<iostream>
unsigned int f(unsigned int n) {
    if (n == 0) {
        return 0;
    } else {
        if (n == 1) {
            return 1;
        } else {
            return f(n - 2) + f(n - 1);
        }
    }
}

int main() {
    unsigned int x = f(5);
    std::cout << x << std::endl;
    return 0;
}