Skip to content
Topos Uranos

Summary

Up to this point every program in the course has been a single block, main, in which everything is written where it is used. This lesson teaches how to give a name to a part of a program and to use it without looking inside it: the function. It studies the declaration, which announces to the compiler the name, the return type and the parameters; the definition, which adds the body; and the call, which transfers control to that body and receives the returned value. It distinguishes what the compiler checks when compiling (that each call agrees with a declaration) from what happens when running (the jump to the definition and the way back). It explains why reaching the end of a function that must return a value without a return is undefined behavior. It follows the execution with the call stack, which keeps one frame for each call in progress. And it specifies each function with a contract, its precondition and its postcondition, which says what the function demands of its caller and what it guarantees in return.

Learning objectives

  1. Declare, define and call functions with parameters and a return value, and point out in a program which part is the declaration and which the definition.
  2. Follow with a call stack diagram the execution of a program with functions that call one another.
  3. Specify a function with its precondition and its postcondition, and write a call that violates the precondition.
  4. Explain why a function that does not return a value on some path is undefined behavior, and recognize the corresponding compiler warning.

Why functions

The programs of the previous unit solved each problem inside main, and that was enough while the problems were small. Now, as soon as a program grows, three difficulties appear. The first is repetition: if the same calculation is needed in three places, it is written three times, and an error in it is fixed three times (or one of the three is forgotten). The second is reading: a block of fifty lines does not say what it does, but how it does it, and the reader must reconstruct the intention from the mechanism. The third is testing: if everything is mixed together, there is no way to check one part without running the rest.

A function is a named fragment of a program that receives data, called parameters, and delivers a result, called the return value. Mathematics has known the idea for centuries: the distance between two points of the plane is a function of their four coordinates, d(x1,y1,x2,y2)=(x2−x1)2+(y2−y1)2d(x_1, y_1, x_2, y_2) = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}, and whoever computes the perimeter of a triangle does not repeat the formula three times, but names it and applies it three times. In C++ one writes the same thing.

ExampleThe perimeter of a triangle

The program reads the coordinates of the three vertices of a triangle and writes its perimeter, which is the sum of the lengths of its three sides.

C++ program
#include <cmath>#include <iostream>#include <print>​// Distance between the points (x1, y1) and (x2, y2).double distance(double x1, double y1, double x2, double y2){    const double dx{x2 - x1};    const double dy{y2 - y1};    return std::sqrt(dx * dx + dy * dy);}​int main(){    double ax{};    double ay{};    double bx{};    double by{};    double cx{};    double cy{};    std::cin >> ax >> ay >> bx >> by >> cx >> cy;    const double perimeter{distance(ax, ay, bx, by) + distance(bx, by, cx, cy)                           + distance(cx, cy, ax, ay)};    std::println("Perimeter: {}", perimeter);}
Program input
0 0 3 0 0 4
Output
Perimeter: 12

The sides of the triangle with vertices (0,0)(0, 0), (3,0)(3, 0) and (0,4)(0, 4) measure 3, 5 and 4, and their sum is 12.

The function distance is written once and used three times; main reads as the definition of the perimeter, “the sum of three distances”; and distance can be tested on its own, with a pair of points whose distance is known. The three things that were missing are thus gained. The general moral, which holds in any language, is that a function names an idea: whoever uses it thinks about what it does, not about how it does it. This separation between use and realization is called procedural abstraction, and it is the theme of the whole unit.