We mentioned compatible types earlier so we should review them just a bit in order to make our discussion of prototyping complete. Compatible types are any simple types that can be converted from one to another in a meaningful way. For example, if you used an integer as the actual parameter and the function was expecting a float type as the formal parameter, the system would do the conversion automatically, without mentioning it to you. This is also true of a float changing to a char, or a char changing to an int. There are definite conversion rules which would be followed. These rules are given in great detail in section 3.2 of the draft of the ANSI-C standard and are also given on page 198 of the second edition of the K&R reference.
If we supplied a pointer to an integer as the actual parameter and expected an integer as the formal parameter in the function, the conversion would not be made because they are two entirely different kinds of values. Likewise, a structure would not be converted automatically to a long float, an array, or even to a different kind of structure, they are all incompatible and cannot be converted in any meaningful manner. The entire issue of type compatibility as discussed in chapter 2 of this tutorial applies equally well to the compatibility of types when calling a function. Likewise, the type specified as the return type, in this case void, must be compatible with the expected return type in the calling statement, or the compiler will issue a warning.
HOW DOES PROTOTYPING WORK?
This is your chance to try prototyping for yourself and see how well it works and what kinds of error messages you get when you do certain wrong things. Change the actual parameters in line 12 to read (12.2, 13, 12345) and see what the compiler says about that change. It will probably say nothing because they are all type compatible. If you change it to read (12.0, 13), it will issue a warning or error because there are not enough arguments given. Likewise you should receive an error message if you change one of the parameters in line 13 to an address by putting an ampersand in front of one of the variable names. Finally, change the first word in line 4 from void to int and see what kind of error message is given. You will first be required to make the function header in line 16 agree with the prototype, then you will find that there is not a variable returned from the function. You should have a good feeling that prototyping is doing something good for you after making these changes.
Be sure to compile and execute this program then make the changes recommended above, attempting to compile it after each change.
A LITTLE MORE PROTOTYPING
Examine the next example program named PROTYPE2.CPP for a little more information on prototyping.
void do_stuff(int, float, char);
int arm = 2;
float foot = 1000.0;
char lookers = 65;
do_stuff(3, 12.0, 67);
do_stuff(arm, foot, lookers);
void do_stuff(int wings, // Number of wings
float feet, // Number of feet
char eyes) // Number of eyes
cout << "There are " << wings << " wings." << "n";
cout << "There are " << feet << " feet." << "n";
cout << "There are " << eyes << " eyes." << "nn";
// Result of execution
// There are 3 wings.
// There are 12 feet.
// There are C eyes.
// There are 2 wings.
// There are 1000 feet.
// There are A eyes.
This program is identical to the last one except for a few small changes. The variable names have been omitted from the prototype in line 4 merely as an illustration that they are interpreted as comments by the C++ compiler. The function header is formatted differently to allow for a comment alongside each of the actual parameters. This should make the function header a little more self explanatory. However, you should remember that comments should not be used to replace careful selection of variable names. In this particular case, the comments add essentially nothing to the clarity of the program.
WHAT DOES PROTOTYPING COST?
Prototyping is essentially free because it costs absolutely nothing concerning the run time size or speed of execution. Prototyping is a compile time check and slows down the compile time a negligible amount because of the extra checking that the compiler must do. If prototyping finds one error for you that you would have had to find with a debugger, it has more than paid for itself
for use in an entire project. I once spent 12 hours of debugging time to find that I forgot to pass the address of a variable to a function. Prototyping would have found the error on the first compilation of this 2000 line program.
The only price you pay to use prototyping is the extra size of the source files because of the prototypes, and the extra time for the compiler to read the prototypes during the compilation process, but both costs are negligible.
Be sure to compile and execute this example program. You will find that it is identical to the last example program.