1.7.2 Communication between Functions

High-level languages allow the definition of three kinds of variables: local, nonlocal and global. A C program consists of functions. A function of a program may reference

1. Local variables, to which it alone has access

2. Nonlocal variables, to which it and some other functions of the program have access

3. Global variables, to which all functions of the program have access

A variable is referenced by a function in order to copy, modify, or simply look at its value.

High-level languages treat variables in differing ways. FORTRAN, for example, considers variables to be local to a function unless they appear as formal parameters of that function (in which case they are nonlocal). Variables stored in special common areas of memory are global. C determines whether a variable is local, nonlocal, or global by using block rules. In Figure 1.3 candidates is local to primes, factor is local to remove, and nextmultiple is local to delete, while n is nonlocal or global to each.

Each high-level language has its own rules to give one function access to variables of another. Merely using the same variable name in two functions will not normally allow one to reference a variable in another. For example, i in create and i in print (Figure 1.3) do not represent the same variable; each is local to its function. If this were not so, functions could not be written independently. Once a complex problem has been refined, different individuals or groups should be able to develop components independently. Otherwise, each time a group used a new variable name, it would have to check that no other group used the same name.

The issue here is really communication between functions of a program. Communication between functions?/FONT>allowing one to reference variables also used by another?/FONT>occurs in two basic ways: using nonlocal or global variables, or using formal parameters in defining functions.

When a function changes the value of a variable used by another, and the variable is not communicated (or passed) between them as a parameter, a side effect has occurred. Side effects make it extremely difficult to understand what functions do. It is easier to see what a function does when we can be sure that only the parameters and the local variables will be affected by the execution of the function. The communication structure of a program is clearer when information is communicated explicitly by the use of parameters. This shows "who is doing what to whom." For example, in delete (Figure 1.3), no side effects can occur, since the only nonlocal variables factor, n, and candidates all appear as parameters. Thus the only variables not local to delete that it can reference are factor, n, and candidates.

At one extreme, it is possible to make all variables global?/FONT>every function may then reference any variable. Making all variables global requires extremely careful adherence to the use of variable names and increases the probability of side effects. COBOL programs are typically written this way. However, such programs use well-defined file structures, deal with high-volume input and output, and use relatively simple algorithms, so this method may not cause difficulty.

The other extreme is to use only parameters between functions. This may not always be possible. For example, storage considerations may intrude, as with arrays in Pascal.

Communication between functions by using parameters may be a one-way or a two-way street. In some high-level languages, like FORTRAN, any change in the value of a parameter in a called function is passed or reflected back to the calling function. Other languages, such as C, allow one component to communicate information to another yet never reflect changes made to the parameter's value. Upon return, the parameter's value is the same as prior to the call. Also, upon return from a call, different languages treat local variables of functions differently. Some preserve their values between calls, while others do not. In FORTRAN it is possible to have local variables retain their values between invocations of a function; in Pascal it is not. In C either case may apply. Values may be preserved or erased as desired.