|
In this tutorial you will experiment with programmer-defined functions in C, as discussed in Chapter 12. You will be using some example programs. You can use your Web browser to download them.
You do not have to write many programs before you realize that you would like to use a function that is not provided by C. Fortunately, it is easy to define and use your own functions. In this section we will look at a simple example of how to do that.
Download log1.c and read it into Emacs. Whereas C provides a function named log10 to compute base ten logarithms, it provides no corresponding function for other integer-valued bases. Because of this, log1.c uses the log10 function to compute logarithms for bases 2 through 9 according to a standard mathematical formula.
If there were a standard function, say logbase, to compute base b logarithms, our program would be simplified in the following ways:
The program log2.c shows what log1.c would look like if a logbase function existed in math.h. If you try to compile it, however, the compiler will complain that it doesn't know anything about the logbase function. If we want to use logbase in our program, we will also have to implement it.
The program log3.c is identical to log2.c except that it also contains an implementation of the programmer-defined function logbase. This program will compile, run, and produce the same results as our original log1.c.
The implementation of logbase appears near the top of log3.c, and is:
/* Returns the log base b of y. */ double logbase (double y, int b) { double lg; lg = log10(y)/log10(b); return(lg); }
The comment together with the first line of the function (known as the header) tell us everything that we need to know in order to make use of logbase. This information, which is called the interface of the function, includes
The comment and the header make it possible to understand what logbase does without having to read the balance of its implementation.
A programmer-defined function is called in exactly the same way as a built-in function. The main function of log3.c contains eight different calls to logbase; the first one, for example, is
logbase(x,2);
which calculates the log base 2 of x.
It is important to use a programmer-defined function in a way that is consistent with its interface; otherwise, you will get compiler errors or unexpected results. To understand this point better, and to get an idea of what kinds of errors you can expect, try these experiments with this line of code from log3.c,
printf("The base 2 logarithm of %g is %g\n", x, logbase(x,2));
which is the first line in the main function that makes use of logbase. (After each experiment, change log3.c back to its original form.)
%g
) to %d
. In other words,
specify that the value returned by logbase(x,2) is to be
displayed as an integer. Compile the program and note the error
message.
When a programmer-defined function is called, C follows a well-defined sequence of steps. For example, let's consider what happens when logbase(x,2) is called.
y | |
b | |
lg |
y | 16.0 |
b | 2 |
lg |
Notice that the first actual parameter supplies the initial value of the first formal parameter, and so on. The names used for the actual and formal parameters have nothing to do with one another. That is why we can pass the value of an actual parameter x to a formal parameter y, and the value of an actual parameter 2 to a formal parameter b.
lg = log10(y)/log10(b); return(lg);
is evaluated, using the just-created table to look up and store the values of variables. When a return statement is encountered, the specified value (in this case lg, which would be 4.0), is returned to the point of call as the result. The variable table is discarded, and execution continues at the original point of call just as if a built-in function had been called.