Previous: 3.1 Designing the Algorithm with Functions
Up: 3.1 Designing the Algorithm with Functions
Previous Page: 3.1 Designing the Algorithm with Functions
Next Page: 3.2 Defining Functions
Abstractly, a function can be viewed a a piece of code which, when given sufficient information, performs some subtask and returns the result, a value. Returning to our example, if a function, calc_pay(), is used to calculate pay, it will need enough information to perform the computation. In this case the data it needs is the number of hours worked and the rate of pay. As we have stated before, variables, such as hours_worked and rate_of_pay, defined in a block are only known, i.e. can be accessed, within that block. So we cannot give calc_pay() direct access to variables defined in other functions, in this case main(). However, calc_pay() does not need direct access to the variables, it only needs the values to be used for the computation. So we can give a function the values it needs by passing them as arguments. We can do this by writing an expression, called a function call, giving the name of the function and expressions for the values of the arguments, e.g.:
calc_pay(hours_worked, rate_of_pay)The arguments passed are the values of hours_worked as the first argument, and rate_of_pay as the second argument. Given this data we know (or at this point simply believe) that the function does the right thing and returns with a value, the total pay. We say that the function call evaluates to a value just as any other expression. The function calc_pay() can now be used in main() as follows:
total_pay = calc_pay(hours_worked, rate_of_pay);In summary, the function main() calls calc_pay() to perform a task using a set of values. The values are passed as a parenthesized list of data items (which can be any valid expressions) separated by commas. The expressions that appear in such a statement calling the function are called arguments. The values of these arguments are received by the called function, calc_pay(), which uses them to perform the desired subtask. Finally, calc_pay() returns the value of total pay to the calling function, main(), where it is assigned to the variable, total_pay.
The value returned by calc_pay() will be the total pay calculated using the values of arguments passed to it. Here are a few additional examples of function calls used in an assignment expression:
total_pay = calc_pay(30.0, 10.0); /* calc_pay() returns 300.0, */
/* which is stored in total_pay. */
total_pay = calc_pay(20.0, 10.0); /* total_pay is assigned 200.0. */
A function call is an expression and has a value. Just as we had to declare the data types of variables to the compiler, we must also declare the data type of a function. This declaration also includes the number of arguments the function requires and their types. For example, here is a declaration for calc_pay():
float calc_pay(float hours, float rate);The declaration states that calc_pay() is a function because the identifier calc_pay is followed by a parenthesized list of arguments, that it requires two float arguments, and that it is of float type, i.e. it returns a float value. This declaration statement for a function (notice it is terminated by a semi-colon) is called a prototype statement because it gives the prototype (or the form) for calls to the function. In general, we will refer to the list of data expected to be passed to a function as specified in the prototype statement as a parameter list and an individual data item in this list as a parameter. (Sometimes, however, the terms parameter and argument are used interchangeably). The names of the parameters in a prototype statment are optional; but including well chosen names for parameters can make the declaration more meaningful. These parameter names are dummy names which have no relation to the names of arguments in a function call or parameters in the function definition (described in the next section).
Let us implement the top level program logic
using the function calc_pay()
to calculate pay. The code is shown in Figure 3.2 and
for simplicity,
we have not included calculation of gross and average_pay.
Figure 3.3 shows the behavior of the function call pictorially. The box labeled main() represents the function main() in our program and contains memory cells for variables declared in main() labeled with their names (e.g. hours_worked). The box labeled calc_pay() represents the function calc_pay(). At this point we do not know anything about the internals of this box such as what variables are declared, and what statements will be executed; but at this point we do not need to know this information. The box shows all of the information we need to know; namely that the function expects two float type arguments to be passed and will return a float type result. The dashed lines in the figure show that, for the call we have written in main():
total_pay = calc_pay(hours_worked, rate_of_pay);the first argument, the value of hours_worked, is passed to the first parameter of calc_pay(), and the second argument, the value of rate_of_pay, is passed to the second parameter. The return value from calc_pay() is placed in the variable by main().
In summary, the function main() represents the overall logic of the program. The details of how pay is actually computed does not change the overall logic. Of course, the program in Figure 3.2 is not yet complete since we have not written the function . If an attempt is made to compile the program at this point, there will be a linker error message stating that the function cannot be found. Only when the function is written is the program complete and may be compiled and executed.