Skip to main content

2.7 Functions

Most large programs have a set of tasks that must be executed many, many times, in different situations - e.g. matrix multiplication. Rahter than writing the code for that task each time the task is required, you can "farm out" these tasks to something called a function. By keeping code for a given task in the one place and just re-using it when you need, functions help modularise your code, making the possibility of bugs creeping in less likely.

To include a function, you must, in a sense "declare" this function, at the top of the code before you start in main. This declaration is known as a function prototype. the prototype is just like a blueprint - it gives the basic structural information of the function, by telling the compiler what the function will return, what the function will be called, as well as what arguments the function can have passed to it. The general format for a prototype is:

return-type function_name ( arg_type arg1, ..., arg_type argN ); 

arg_type is the type for each argument -- for instance, an int, a float, or a char. It's exactly the same thing as what you would put if you were declaring a variable. The return type is the same (e.g. return type int will return an integer value) with one exception - the return type void. If a function has a void return type, then it does not return a value. You can also have the case of no arguments being passed, signified by empty brackets () - yuo've already seen this for the main part of the code. Don't forget to put the semicolon at the end of this prototype statement.

Example:

Below is an example of a prototype of a function, prod, that takes two integer numbers as input and returns a floating point number:
int prod (int a, int b);

After the main part of the code is where functions are usually defined. The function definition begins with the prototype, minus the semi-colon. Then put the statements you wish to execute in your function in a block statement (see Section 2.5.1) Any of the arguments passed to the function can be used as if they were declared in the block. Following on from the above example, below is a code fragment defining a function:

Example:

Below is an example of a function defintion for prod, that takes two integer numbers as input, multiplies them together and returns the product:
int prod (int a, int b)
{
  return a * b;
}

Prototypes are put at the top of the program to alert the compiler to the fact that the main part of the code will be calling this function. If you did not use a prototype in this case, the compiler would not know what "prod" was, and your build would fail. You can however have a prototype with out defining the corresponding function, although clearly nothing will happen if this non-existent function is called within the code.

Putting it into Practice:

Code up the program below to see how this all fits together.
#include<stdio.h>	

int prod ( int a, int b );

int main()
{
  int a;
  int b;
  char line[50];
  
  printf( "Please input two integers to be multiplied and hit return: " );
  fgets(line,sizeof(line),stdin);
  sscanf(line,"%d %d",&a,&b);
  printf( "The product of your two numbers is %d\n", prod( a, b ) );
  return 0;
}

int prod (int a, int b)
{
  return a * b;
}
Compile and run this code. Try writing some variations on this code.

Arguments are always passed by value in c function calls. This means that local "copies" of the values of the arguments are passed to a function. Any change made to the arguments internally in the function are made only to the local copies of the arguments. In order to change (or define) an argument in the argument list, this argument must be passed as an address - this involves using pointers (more on this later).