Module 4. Functions

Lesson 13

FUNCTIONS IN ‘C’ – PART I

(Declaration, Function Prototypes, Parameter Passing and Function Access)

13.1  Functions

A function is a self-contained block of statements, which performs some specific, well-defined task and always returns a single value to the calling function. Every ‘C’ function comprises of one or more functions; one of which must be defined as main. The programme execution begins with carrying out the instructions contained in the main function. All other functions, if any, being a part of the programme will be subordinate to the main function. If the programme contains several functions, their definitions may appear in any order, though they must be independent of each other. A function can be accessed or called from different points in a programme. Generally, a function will process the information passed through the calling point of the programme and returns a single value as a result. This information is passed to the function through special identifiers called arguments or parameters and the function output (a single value) is returned by means of the return statement. Thus, once the function has completed its intended task, the control automatically reaches back to the calling point. On the other hand, some functions accept information but do not return anything, e.g., library function printf, while other functions such as scanf return multiple values. Evidently, functions are used to minimise the repetition of code. There are two types of function in ‘C’ as described below.

13.2  Programmer-defined Function Declaration, Parameter Passing and Function Access

A function written by a programmer is called programmer-defined function. The function definition has two principal components; the first line that includes the argument declaration and the body of the function. The general syntax of the function statement is:

datatype name(type 1 arg_1, type 2 arg_2, …, type n arg_n)

where datatype represents the data type of the resultant value returned by the function after execution of the instructions contained in the body of the function; name represents the function name for reference by other functions; and type 1, type 2, …, type n are the data types of the arguments arg_1, arg_2, …, and arg_n. Note that the data types are assumed to be of the type int if they are not declared explicitly. 

An illustration

The following code segment demonstrates as to how to define and access functions in a programme. Note that add is the function that computes sum of two integer numbers supplied through the main function while calling the same. Always, remember that the arguments and the corresponding actual variables should be same in type, order and number. 

int add (int x, int y) 

{

int z;

z = x + y;

return (z);     

}

void main()

{

int i, j, k;
i = 15;
j = 5;
k = add(i, j);

printf ("The value of k is %d\n", k);  

}

Output

The value of k is 20.

13.3  Function Prototypes

In the above programme, you have seen that the programmer-defined function preceded the main function. Thus, when this programme is compiled the programmer-defined function will have been defined before the first access. However, many programmers prefer a top-down approach, in which the main function appears ahead of the programmer-defined function. In such situations, the function access (from within the main) will precede the function definition. This sounds confusing to the compiler, unless the compiler is first instructed that the function being accessed will be defined later in the programme. A function prototype is used for this purpose. The function prototype is usually written at the beginning of the programme, i.e., ahead of any programmer-defined function including the main function. The general syntax of the function prototype is:

datatype name(type 1 arg_1, type 2 arg_2, …, type n arg_n);

where datatype represents the data type of the resultant value returned by the function after execution of the instructions contained in the body of the function; name represents the function name for reference by other functions; and type 1, type 2, …, type n are the data types of the arguments arg_1, arg_2, …, and arg_n. Note that the data types are assumed to be of the type int if they are not declared explicitly. You might have noticed that the function prototype resembles the first line of a function definition statement (though, a function prototype ends with a semicolon!). Also, note that the names of the arguments within the function prototype need not be declared elsewhere in the programme, since these are dummy arguments that are recognised only within the prototype. In fact, the argument names can be omitted; however, the argument data types are essential. Function prototypes are not essential but desirable as they facilitate error checking between the calls to a function and the corresponding function definition.

An illustration

The programme discussed in the previous section is revised to demonstrate the effect of the function prototype as follows:

int add (int x, int y); 

void main()

{

int i, j, k;
i = 15;
j = 5;
k = add(i, j);

printf ("The value of k is %d\n", k);  

}

int add (int x, int y)

{

int z;

z = x + y;

return (z);     

}

Output

The value of k is 20.

13.4  Scope of Function

Only a limited amount of information is available within the body of each function. Variables declared within the calling function cannot be accessed from the outside functions unless they are passed to the called function as arguments.

13.5  Global Variables

A variable that is declared outside all functions is called global variable. Global variables do not die on return from a function. Their value is retained and is available to any other function within the whole programme.

13.6  Local Variables

A variable that is declared within a function is called local variable. They are created each time the function is called and destroyed on return from the function. The values passed to the functions (arguments) are also treated like local variables.

13.7  Static Variables

Static variables are like local variables but they do not die on return from the function. Instead, their last value is retained and it becomes available when the function is called again.

13.8  Parameter Passing in ‘C’

The function is a self contained block of statements, which performs a coherent task of a same kind. ‘C’ programme does not execute the functions directly, rather it is required to invoke or call such functions. When a function is called in a programme then programme control goes to the function body and it executes the statements, which are involved in a function body. Therefore, it is possible to call function whenever you want to process those function-statements.

In ‘C’ language, when you call a function you can pass arguments in two ways:

Pass by value

When you use pass-by-value method, the compiler copies the value of an argument in a calling function to a corresponding non-pointer or non-reference parameter in the called function definition. The parameter in the called function is initialised with the value of the passed argument. As long as the parameter has not been declared as constant, the value of the parameter can be changed, but the changes are performed within the scope of the called function only; they have no effect on the value of the argument in the calling function.

In the following example, main function passes two values: 5 and 7 to function, func. The function func receives copies of these values and accesses them by the identifiers a and b. The function func changes the value of a. When control passes back to main, the actual values of x and y are not changed.

Illustration: The following programme demonstrates calling a function ‘by value’ method

// pass by value

#include <stdio.h>

void func(int a, int b)

{

   printf("Before processing, In func, a = %d    b = %d\n", a, b);

   a += b;

   printf("After processing, In func, a = %d    b = %d\n", a, b);

}

int main()

{

   int x = 5, y = 7;

   printf("Before function call, In main, x = %d   y = %d\n", x, y);

   func(x, y); //function call by value

   printf("After function call, In main, x = %d    y = %d\n", x, y);

   return 0;

}

Output:

Before function call, In main, x = 5    y = 7

Before processing, In func, a = 5    b = 7

After processing, In func, a = 12    b = 7

After function call, In main, x = 5    y = 7

Example 1:  Programme to print numbers 1 through 100 without using loop.

#include<stdio.h>

int main()

{

    int num = 1;

    print(num);

    return 0;

}

int print(num)

{

    if(num<=100)

    {

         printf("%d ",num);

         print(num+1);

    }

    return(num);

}

Output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

Pass by reference

Passing by reference refers to a method of passing the address of an argument in the calling function to a corresponding parameter in the called function. In ‘C’, the corresponding parameter in the called function must be declared as a pointer type (an advanced topic, which is discussed later in Module-V; thus, students may better comprehend ‘pass by reference’ method after reading the pointers in ‘C’).

In this way, the value of the argument in the calling function can be modified by the called function.

Illustration: The following example shows how arguments are passed by reference. Note that the pointer parameters are initialised with pointer values when the function is called.

// pass by reference

#include <stdio.h>

void swapnum(int *i, int *j)

{

  int temp;

  temp = *i;

 *i = *j;

 *j = temp;

}

int main()

{

  int a = 10, b = 20;

  printf("Before function call: a is %d and b is %d\n", a, b);

  swapnum(&a, &b);

  printf("After function call: a is %d and b is %d\n", a, b);

  return 0;

}

Note that when the function swapnum is called, the actual values of the variables a and b are swapped because they are passed by reference. This means that using these addresses, we would have an access to the actual arguments. Hence, we would be able to manipulate them. Interestingly, ‘C’ does not support call by reference, as such! However, it can be simulated using pointers as demonstrated in this illustration.

Output:

Before function call: a is 10 and b is 20

After function call: a is 20 and b is 10

13.9  Passing Arrays as Arguments

Array arguments are passed in a different way than the single-valued data items. If an array variable name is specified as an actual argument, the individual array elements are not copied. Rather, the location of the array (i.e., the location or address of the first element) is passed to the function. If an element of the array is accessed from within the function, the access will refer to the location of that array element relative to the location of the first element. Thus, any alteration to an array element within the function will carry over to the calling routine. There are other types of data structures that can be passed as arguments to a function. The interested students may like to refer to the resources mentioned under ‘Suggested Readings’ section at the end of this lesson as well as to the Module V for further exploration in this direction.