We write Program P7.1 to show how skipLines fits into a complete program.
Program P7.1
#include <stdio.h>
int main() {
void skipLines(int);
printf("Sing a song of sixpence\n");
skipLines(2);
printf("A pocket full of rye\n");
} //end main
void skipLines(int n) {
for (int h = 1; h <= n; h++) printf("\n");
} //end skipLines
When we wish to use a variable in main, we must declare the variable in main. Similarly, if we want to use skipLines in main, we must tell C about it using what is called a function prototype. A function prototype is a declaration pretty much like the function header. In the program, we use the prototype:
void skipLines(int);
The prototype describes the function by stating the return type of the function (void, in this case), the name of the function (skipLines) and the type(s) of any argument(s) (int, in this example). If you wish, you can write a variable after the type, as in:
void skipLines(int a);
This variable will be used by the compiler only if it needs to generate an error message. In this book, we will write our prototypes using the type only.
Note that the function prototype is followed by a semicolon whereas the function header is followed by a left brace.
As another example, the prototype int max(int, int);
says that max is a function that takes two integer arguments and returns an integer value.
A common mistake made by beginners is to forget to write the function prototype. However, that is not a big problem. If you forget, the compiler will remind you of it. It is like forgetting to declare a variable – the compiler will tell you about it. You just fix it and move on.
In terms of layout, the functions, including main, which make up a C program can appear in any order. However, it is customary to place main first where the overall logic of the program can be easily seen.
We emphasize that this program is for illustrative purposes only since the output could be produced more easily with this:
printf("Sing a song of sixpence\n\n\n");
printf("A pocket full of rye\n");
7.3.1 The Function Header
In our example, we used the function header void skipLines(int n)
In general, the function header consists of:
• a type (such as void, int, double, char), which specifies the type of value returned by the function. If no value is returned, we use the word void. The function skipLines does not return a value so we use void.
• the name we make up for the function, skipLines in the example.
• zero or more parameters, called the parameter list, enclosed in brackets; one parameter n of type int is used in the example. If there are no parameters, the brackets must still be present, as in printHeading().
The function header is followed by the left brace of the body.
Parameters are specified in the same way variables are declared. In fact, they really are declarations. The following are all valid examples of headers of void functions:
void sample1(int m, int n) // 2 parameters void sample2(double a, int n, char c) // 3 parameters void sample3(double a, double b, int j, int k) // 4 parameters
Each parameter must be declared individually and two consecutive declarations are separated by a comma. For example, it is invalid to write
void sample1(int m, n) //not valid; must write (int m, int n) Shortly, we will see examples of functions that return a value.
7.3.2 How a Function Gets Its Data
A function is like a mini program. In the programs we have written, we have stated what data must be supplied to the program, what processing must take place, and what the output (results) should be. We must do the same when we write a function.
When we write a function header, we use the parameter list to specify what data must be supplied to the function when it is called. The list specifies how many data items, the type of the each item, and the order in which they must be supplied.
For example, we wrote skipLines with an integer parameter n; this says that an integer value must be supplied to skipLines when it is called. When skipLines is called, the argument supplied becomes the specific value of n and the function is executed assuming that n has this value. In the call skipLines(3), the argument 3 is the data that skipLines needs to perform its job.
It is worth emphasizing that main gets its data by using scanf, among other functions, to read and store the data in variables. On the other hand, a function gets its data when it is called. The variables in the parameter list are set to the values of the corresponding arguments used in the call. For example, when we write the header
void sample(int n, char c, double b)
we are saying that, when we call sample, we must do so with three arguments: the first must be an int value, the second a char value and the third a double value.
Assuming that num is int, ch is char and x is double, the following are all valid calls to sample:
sample(25, 'T', 7.5);
sample(num, 'A', x);
sample(num, ch, 7); //an int argument can match a double parameter sample(num + 1, ch, x / 2.0);
If, when a function is called, the type of an argument is not the same as the corresponding parameter, C tries to convert the argument to the required type. For example, in the call sample(num, 72, 'E');
the value 72 is converted to char and the parameter c is set to 'H' (since the code for H is 72); the numeric value of 'E' (which is 69) is converted to the double value 69.0 and the parameter b is set to 69.0.
If it is not possible to convert the argument to the required type, you will get a “type mismatch” error, as in the call
sample(num, ch, "hi"); // error - cannot convert string to double
You will also get an error if you do not supply the required number of arguments, as in sample(num, x); // error - must have 3 arguments