CSC 115.005/006 Sonoma State University Spring 2022
Scribbler 2
CSC 115.005/006:
Programming I
Scribbler 2
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College


Course Home References Course Details: Syllabus, Schedule, Deadlines, Topic organization MyroC Documentation Project Scope/
Acknowledgments

Notes:

Function Prototypes and
an Overview of Functions with Address Parameters, Arrays, and Testing

Introduction

As we have explored problem solving using C, main topics have included variables for several types of data, control structures, such as conditional statements (if, switch), loops (for, while), program organization including simple functions, and assertions.

To move our problem solving to a deeper and more sophisticated level, the next step is to explore two issues:

This reading addresses the minor issue, by introducing the concept of function prototypes. The rest of this course segment discusses the storage of data within a computer's main memory, focusing on three foundational topics:

C Provides Low-level Machine Access

The C programming language provides considerable access to data in main memory with few checks or constraints. In general, an underlying principle is that a programmer knows what work needs to be done, and the language provides mechanisms to perform that work directly.

With this capacity to access and manipulate data directly, processing with C can be particularly efficient. Further, C often is the language of choice for low-level problem solving, such as developing operating systems or handling network communications. Of course, unencumbered access to data also implies the capability to generate errors with little checking or second guessing.

Up until now in the course, we have been able to focus on relatively high-level problem solving (e.g., variables, conditional statements, loops, and simple functions). At this point in the course, however, we need to explore low-level details within C more closely. As we shall discover, much processing within C depends upon the layout within main memory of variables, parameters, and other elements.

Observation/encouragement to readers: Much of this material will be new to many students, so readers may find that it takes some time to become comfortable with various concepts. Some ideas may seem reasonable, but it takes a moderate amount of experience to incorporate these concepts into one's problem solving and to become proficient and consistent in writing programs using these ideas.

If elements of this course segment seem awkward at first, be patient! The experience of many students indicates that these ideas will come together dependably with practice.


Function Prototypes

Consider the work of a compiler. A compiler reads a C program line-by-line and translates each statement to machine language, so the resulting code can be run. Although the art of constructing an efficient and effective compiler requires considerable skill, some elements are relatively straight forward:

Challenges arise, however, when functions are used. As a simple example, consider the following function that adds 2.0 to its parameter and returns the result.

double add2 (double value)
{
   return 2.0 + value;
}

Now suppose the main program contains the following lines:

int x = 5;
double y = add2(x);

If the compiler knows about this function before it encounters the expression add2(x), then the compiler will recognize that the int 5 must be converted to the double 5.0 before the function is applied. However, if the compiler has not encountered the definition of add2 previously, the compiler could not know whether the parameter for add2 should be an int or double.

Given this possible confusion, C allows three approaches.

Altogether, a function prototype provides information about the parameters and return type of a function at the start of a program. In summary, a function prototype allows a compiler to generate appropriate code, even if the full details of a function have not yet been given within a program. Of course, if a function prototype is used, the full definition of the function (duplicated header together with the function body) must be defined before the program can be run.

Using Function Prototypes and Supplying Function Details

Program add2.c illustrates a complete program using the add2 function prototype early in the code and giving the details of the function near the end.

/* Program illustrating a function prototype near the start of the code
   and the full function definition near the end.
*/

#include <stdio.h>

/* function to add 2 to a value and return the result */
double add2 (double value);   // function prototype, with semi-colon at end

A function prototype indicates the number and type of parameters and the return type of the function.


int main ()
{
  printf ("program illustrating a function prototype\n");
  int x = 5;
  double y = add2(x);         // function used

  printf ("x = %d, y = %lf\n", x, y);

  return 0;
}

/* function to add 2 to a value and return the result */
double add2 (double value)   // function details given here
{
   return 2.0 + value;
}

This program supplies the details for add2 near the end of the program.


Why Use Function Prototypes?

Although the program add2.c illustrates how function prototypes can be defined and used, a student still may wonder why? Why not just remove the function prototype in a program and place the function header, with its function body, at the start of the code?

Frankly, for program add2, moving the function header and body to the top of the code, replacing the function prototype, would work fine! However, for more complex problems and environments, there can be at least three motivations for the use of function prototypes.


When libraries are used, the function bodies are compiled separately, so you do not have to wait for that material to be compiled when you are compiling your own MyroC programs. Then, when your program is compiled, as your program starts to run, the library functions (the details from the relevant function bodies) are linked into your program to yield a complete program.

Overall, function prototypes associated with C libraries allow compilers to incorporate C functions into programs, by specifying what parameters and return types can be expected for each function.


As a simple example, the rBeep command telling a robot to beep requires both a frequency and a duration. In practice, a programmer may remember that two parameters are needed, but it is easy to forget whether duration or frequency comes first. Consulting the rBeep function prototype indicates duration is the first parameter, and finding this in the header file is relatively quick. In contrast, a full listing of the function bodies for MyroC involves about 24,000 lines — not something to search quickly! Similar comments apply to programs containing numerous functions that you write yourself


For example, if function A were defined first, then there would be a reference to function B, but the compiler would not know the details of B yet. Similarly, if function B were defined first, the compiler would not know about A. With function prototypes, the compiler will know about the parameters and return type of both functions at the start. Then, when the compiler encounters the calls in the function bodies, the compiler already knows how to interpret each context.





created 6 August 2016 by Henry M. Walker
revised 10 August 2016 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.