# Functions

## Introduction

As with Scheme, a function or procedure in C is designed to perform a task. Several variations are possible, such as the following:

• The task may be self contained, or it it may depend upon some starting data.
• The task may or may not change its environment (e.g., the task might move the robot or print something to a terminal window).
• When the task finishes, data may or may not be computed and returned for use in the main program.

Altogether, a function or procedure performs some work. They are used to abstract the work into a single coherent operation. Variations arise in whether or not data are needed to start the work and whether or not computed results are returned to the main program.

In this reading, we examine how functions are created and used in the C programming language. Some functions may take values as parameters, as you are likely accustomed to in Scheme. Similarly, some functions return values, while others are simply called for their side effect. When such functions produce no value, their return type is `void`.

• King: Sections 9.1-9.2, 9.4, pages 183-192, 201-202

## Examples

Using the textbook as background, examine the following programs.

### `quadratic`

`quadratic.c`
``````/* program to illustrate 4 functions related to the quadratic formula
given a, b, and c, the formula computes solutions to
a * x^2 +b * x + c = 0
if discriminant = sqrt (b*b - 4*a*c), a != 0, and discriminant > 0,
then the two real solutions of this equation are
(-b + discriminant) / (2.0 * a)
and
(-b - discriminant) / (2.0 * a)

This variant was created by Jerod Weinman, based on a program developed by
Henry Walker.  The majority of the differences are reflected in the

compile, linking with the math library, using the line
*/

#include <stdio.h>
#include <math.h>

/* Print a quadratic equation given the coefficients. */
void
printEquation (double coeff2, double coeff1, double coeff0)
{
printf ("Equation:  %lf*x^2 + %lf*x + %lf = 0\n", coeff2, coeff1, coeff0);
} // printEqn

/* Compute the discriminant of a quadratic equation
*   r*x^2 + s*x + t = 0 given the coefficients r, s, and t.
*
*  Precondition:
*    s*s >= 4*r*t
*  Postcondition:
*    returns the square root of s*s - 4*r*t
*/
double
computeDiscriminant (double r, double s, double t)
{
return sqrt (s*s - 4*r*t);
} // disc

/* Print both roots of a quadratic equation a*x^2 + b*x + c = 0.
*
* Preconditions:
*   Both roots must be real
*   a != 0
*/
void
printRoots (double a, double b, double c)
{
double discriminant = computeDiscriminant (a, b, c);
double root1 =  (-b + discriminant) / (2.0 * a);
double root2 =  (-b - discriminant) / (2.0 * a);

printf ("    Roots:  %lf and %lf\n", root1, root2);
} // printRoots

/* Control processing for x^2 - 3*x + 2.0 = 0: prints equation and its roots */
void
displayExample1 (void)
{
printEquation (1.0, -3.0, 2.0);
printRoots (1.0, -3.0, 2.0);
} // eqn1

/* Control processing for 2.0*x^2 - 7.0*x - 4.0 = 0;
* prints equation and its roots */
void
displayExample2 (void)
{
printEquation (2.0, -7.0, -4.0);
printRoots (2.0, -7.0, -4.0);
} // eqn2

/* Main function illustrating two equations with their solution via the
int
main (void)
{
printf ("program illustrating functions and the quadratic formula\n");

displayExample1();
displayExample2();

return 0;
} // main``````

### `yoyo`

`yoyo.c`
``````/* program to use functions with value parameters to control a robot */

#include <stdio.h>
#include <MyroC.h>
#include <unistd.h>

/* yoyo illustrates:
function with 1 parameter:  count
2 local variables: i, reps
1 return value
*/
int
yoyo (int count)
{
int reps = 3*count;

/* repeat motion */
for (int i = 0; i < reps; i++)
{
rForward (1, .5);
rBackward (1, .5);
}

sleep (3);

/* print local variables */
printf ("in yoyo:  count = %d, reps = %d\n", count, reps);

return reps;
} // yoyo

/* main demonstrates a call to function with return value */
int
main (void)
{
rConnect ("/dev/rfcomm0");

int repetitions, result;

repetitions = 2;
result = yoyo (repetitions);
printf ("repetitions = %d,   result = %d\n", repetitions, result);

rDisconnect();
return 0;
} // main
``````

### `value-params`

`value-params.c`
``````/* value-params.c
*
* Demonstrates scoping of variable names and passing values into functions.
*/

#include <stdio.h>

int
procA (int a, int b)
{
printf ("procA1  a=%d, b=%d\n", a, b);
a = 5;
b = 6;
printf ("procA2  a=%d, b=%d\n", a, b);
return a + b;
} // procA

void
procB (int x, int y)
{
int z = procA (x, y);
printf ("procB1  x=%d, y=%d, z=%d\n", x, y, z);
x = 5;
y = 6;
printf ("procB2  x=%d, y=%d, z=%d\n", x, y, z);
} // procB

int
main (void)
{
int x, y;
x = 2;
y = 3;
printf ("main1   x=%d, y=%d\n", x, y);
procB (y, x);
printf ("main2   x=%d, y=%d\n", x, y);

return 0;
} // procB
``````

## Schematic Memory Diagrams

When analyzing a C program, it often is helpful to create a schematic of a computer's memory. Overall, each procedure requires memory for its parameters and any local variables. This amount of space is allocated whenever the procedure is called, and this space is deallocated when the procedure finishes.

In a previous reading, we called abstract versions of these notions stack diagrams. We briefly revisit this notion now that we have a firmer idea of functions that take parameters as well.

The stack diagrams we draw are augmented with function parameters appearing in the stack frame alongside the local variables for the function. When the function returns and the stack frame is removed, all the local variables and parameters for that function call are removed. To clarify, consider the original `yoyo.c` program. When the program begins, space is allocated for the variables, `repetitions` and `result` in the `main` procedure. The assignment `repetitions = 2;` stores the number 2 in the location for the `repetitions` variable. When the `yoyo` procedure is called, new space is allocated for the parameter `count` and for local variables `i` and `reps`. During the call to `yoyo`, the value of the variable `repetitions` is copied into the space for the parameter `count`. That is, the value 2 is now stored in two places (e.g., `repetitions` and `count`).

When `yoyo` executes, `reps` is given the value 6. The variable `i` takes on successive values 0, 1, 2, 3, 4, 5, and 6.

As `yoyo` finishes, it returns the value of `reps` (6). When `yoyo` is finished, its space is deallocated, and the returned value is stored in variable `result`.

## Self-check exercise

Consider the following C function:

``````void
change (int x)
{
x = 3;
} // change``````

And the following main function that exercises change:

``````int
main (void)
{
int x = 0;
change(x);
printf("%d\n", x);
}// main``````
1. Before running the program, predict what `main` prints to the console.
2. Verify you prediction by compiling and running the program.
3. Explain the results using the stack-based model of computation. Function parameters are simply local variables (initialized to their arguments). What value does `x` in `change` contain and what is the effect of the assignment in `change`?
The Self-check exercise a derivative work of an exercise by Titus Klinge and Peter-Michael Osera, used under a Creative Commons Attribution-NonCommercial 4.0 license.