Functions and Parameter Passing


Background

When a program is being written, each step in its algorithm is written as one or more statements (typed commands) in the source code. Those statements are later translated into the machine language of a computer and stored on disk for later execution. Later, the program is loaded into main memory and executed. During execution, the computer copies each statement one-at-a-time from the main memory into the processor where it is decoded and executed. The processor keeps track of the the location of the next statement to be loaded by storing that statement's memory address, known as the instruction pointer. Normally, as a program is read, the pointer is simply advanced sequentially from the address of first statement to the next, to the next, and so on. We often find it useful to be able to isolate or extract a block of statements from a program and give that block a name. Such blocks of statements are known as functions (a.k.a. procedures, modules, or subroutines). Once a function's identifier is declared and its statements are recorded, we can use it as many times as necessary (without having to retype the statements) by simply calling it (typing its name) at each point within a program where it is needed. The only restriction on this practice is that a function name must be declared in the source code ahead of where it is called. This modular approach to coding offers a number of advantages.

  1. A program can be developed quickly in general terms just using the names of functions in place of their details. Those details can be defined at a later time. Until then, the program still reads clearly, but in simpler terms. This approach to program definition is referred to as procedural abstraction.
  2. A group of statements that occurs repeatedly in a program can be written (only once) as a function, but then called as often as needed. This technique reduces the presence of redundant (unnecessarily repetetive) code in a program, making it smaller and more efficient.
  3. A function that is judged to be useful in one program can be easily extracted and used in another program. In fact, huge libraries of functions and objects have been developed in this manner. Most compiler software includes an extensive library of functions and object for use by programmers. Our C++ compiler offers these to us in header files, such as the file iostream. The popular C++ objects cout and cin are actually pre-written objects that were declared within the iostream header file.

Parameter Passing

In addition to performing statements, a function can be passed one or more data values to use when it is called. These values are known as arguments or parameters. In C++ source code, arguments are listed in parentheses in the calling statement following the function name. A function also can return (pass back) data to the calling function. In most programming languages, a function can return only a single value (other programming methods are used when more than one value needs to be returned by a function - see Pointers and Indirection). The C++ Language offers a variety of techniques for passing various quantities of parameters between functions. These techniques are discussed on the web page about Function Usage in C++.

Calling a Function

Every C++ program contains at least one function. Its name must be main (all lowercase). Program execution always begins with the main function. Any function can call other functions. When one function calls another, the calling (currently active) function is referred to as the parent function and the called (about to be executed) function is known as a child function. A function's name must be declared in the source code before it can be called. When a parent calls a child, the computer remembers the position of the instruction pointer which points to the address of the next statement in the parent function. The address is recorded in a special memory area known as the stack. The computer then jumps to the position in the code where the child function is defined and executes those statements. When execution of the child function is complete, the computer retrieves the saved instruction pointer from the stack and uses it to jump back to the position of the call in the parent function, where it continues executing the following statements.

The main Function

When we write C++ source code, most of what we do is to declare functions. The following C++ source code provides a simple example of a declaration for the main function.

   int main (void)
   {
        cout << "Hello";
        return 0;
   }

The main function above is declared ahead of its identifier as type int, meaning that it will return an integer value to the calling program (probably the computer's operating system). The parameter list that follows the main identifier in parentheses is void, meaning that this program is not expected to receive any data from its parent when it is called. In other words, when the operating system runs this program, it will not be sending any data to it, but will it be expecting an item of data returned. It is common practice today to write each program's main function in a program so that it return a number to its parent (usually the operating system) to report its exit status (condition when it terminated execution). Typically, a program will return the number zero when it terminates normally, or it will return another number representing an error code when it terminates as the result of some error condition. Notice the use of the return statement as the last statement in the program to return the zero exit code to the parent program. Functions that do not return values to their parent function when done should be declared with a data type of void. Functions that do return values to their parent function when done must be declared with a data type appropriate to the value being returned.


Types of Parameters: "Actual" and "Formal"

Identifiers used in a child function are declared locally (isolated from other functions) to insure that the child function will be "autonomous", meaning that its source code will be complete and independent from any other code. This approach allows us to easily reuse a function that was developed for one program inside of a different program. The source code can simply be copied and pasted into the new program and it should compile there just as well as it did in the original without conflicting with any identifiers already in use in that program.

As a result of this approach, when a piece of data is passed from a parent function (such as main) into a child function, the label used to identify the data in a main function does not have to be identical to the one used for the same value in the child function. A parameter label used in a calling statement is known as an actual parameter. A parameter identifier defined in the declaration of the child function is known as a formal parameter. It is possible to pass more than one parameter into a function, so there can be more than one actual parameter label in a calling statement and more than one formal parameter label declared in a corresponding function declaration. The important thing is that you have the same quantity of each. For more information on actual and formal parameter correspondence, see the web page about Parameter Passing in C++.

PATH: Instructional Server> COP 2000> Examples>