0% found this document useful (0 votes)
12 views

Lecture 6 - Functions

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Lecture 6 - Functions

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

LECTURE 6 – FUNCTIONS

Contents
Introduction .................................................................................................................................................. 1
Why Use Functions?...................................................................................................................................... 2
Defining a Function ....................................................................................................................................... 2
Accessing a Function ..................................................................................................................................... 3
Example 1: Factorial of an integer n ........................................................................................................ 4
Example 2: Factorial of an integer n (return type not specified)............................................................ 4
FUNCTION EXAMPLES: .................................................................................................................................. 6
Void function ............................................................................................................................................. 6
Non-void function ..................................................................................................................................... 6
-User defined function .............................................................................................................................. 7
-Inbuilt function ........................................................................................................................................ 7
Example 4: Determining the maximum of two integers (Complete program) ...................................... 7
Function Prototypes ...................................................................................................................................... 8
Example 6: Factorial of an integer n ....................................................................................................... 9
Parameter Passing in C Functions ............................................................................................................... 11
The Scope of Variables ................................................................................................................................ 16
Recursion..................................................................................................................................................... 16
Example: factorial in recursive form...................................................................................................... 17
Revision Exercises........................................................................................................................................ 18

Introduction
A function is a self-contained program segment that carries out some specific well-defined task. Every C
program consists of one or more functions. One of these functions must be called main. Execution of the
program will always begin by carrying out the instructions in main. Additional functions will be
subordinate to the main, and perhaps to one another.

If a program contains multiple functions, their definitions may appear in any order, though they must be
independent of one another. That is, one function definition cannot be embedded within another. A
function will carry out its intended action whenever it is accessed (whenever the function is called) from
some other portion of the program. The same function can be accessed from several different places
within a program. Once the function has carried out its intended action, control will be returned to the
point from which the function was accessed.

Generally, the function will process information that is passed to it from the calling portion of the
program and return a single value. Information is passed to the function via special identifiers called
arguments (also called parameters) and returned via the return statement. Some functions, however,
accept information but do not return anything.

Why Use Functions?


The use of programmer-defined functions allows a large program to be broken down into several
smaller, self-contained components each of which has some unique identifiable purpose. Thus, a C
program can be modularized through the intelligent use of functions.

There are several advantages to this modular approach to program development; for example, many
programs require that a particular group of instructions be accessed repeatedly from several different
places in the program. The repeated instructions can be placed within a single function which can then
be accessed whenever it is needed. Moreover, a different set of data can be transferred to the function
each time it is accessed. Thus, the use of a function eliminates the need for redundant programming of
the same instructions.

Equally important is the logical clarity resulting from the decomposition of a program into several
concise functions where each function represents some well-defined part of the overall problem. Such
programs are easier to write and easier to debug and their logical structure is more apparent than
programs which lack this type of structure. This is especially true of lengthy, complicated programs.
Most C programs are therefore modularized in this manner, even though they may not involve repeated
execution of some task. In fact the decomposition of a program into individual program modules is
generally considered to be good programming practice.

This use of functions also enables a programmer to build a customized library of frequently used
routines or of routines containing system-dependent features. Each routine can be programmed as a
separate function and stored within a special library file. If a program requires a particular routine, the
corresponding library function can be accessed and attached to the program during the compilation
process. Hence a single function can be utilized by many different programs.

Defining a Function
A function definition has two principle components; the first line (including the argument declaration),
and the body of a function.

-The first line of a function definition contains the value returned by the function, followed by the
function name, and (optionally) a set of arguments separated by commas and enclosed in parenthesis.
Each argument is preceded by its associated type declaration. Any empty pair of parenthesis must follow
the function name if the function definition does not include any arguments.

In general terms, the first line can be written as:


data-type functionname (type 1 argument 1 , type 2 argument 2 ,……, type n argument n )
Where data-type represents the data type of the item that is returned by the function.
functionname represents the function name , and type 1 , type 2 ,…….., type n represents the data types
of the arguments, argument 1, argument 2 ,……..argument n .

The data types are assumed to be of type int if they are not shown explicitly. However, the omission of
the data type is considered poor programming practice, even if the data items are integers.

The arguments are called formal arguments because they represent the names of data items that are
transferred into the function from the calling portion of the program. They are also known as
parameters or formal parameters. (The corresponding arguments in the function reference are called
actual arguments since they define the data items that are actually transferred). The names of the
formal arguments need not be the same as the names of the actual arguments in the calling portion of
the program. Each formal argument must be of the same data type, however, as the data item it
receives from the calling portion of the program.

-The remainder/second part of the function definition is a compound statement that defines the action
to be taken by the function. This compound statement is sometimes referred to as the body of the
function. Like any other compound statement, this statement can contain expressions statements, other
compound statements, control statements and so on. It should include one or more return statements
in order to return a value to the calling portion of the program. A function can access other functions. In
fact it can access itself (a process known as recursion).

-Information is returned from the function to the calling portion of the program via a return statement.
The return statement also causes the program logic to return to the point from which the function was
accessed.
In general terms the return statement is written as:

Return (expression);

Only one expression can be included in the return statement. Thus, a function can return only one value
to the calling portion via return.

Accessing a Function
-A function can be accessed by specifying its name followed by a list of arguments enclosed in
parenthesis and separated by commas. If the function call does not require any arguments an empty
pair of parenthesis must follow the name of the function. The function call may be part of a simple
expression (such as an assignment statement), or it may be one of the operands within an expression.

-The arguments appearing in the function are referred to as actual arguments in contrast to the formal
arguments that appear in the first line of the function definition. (They are also known as actual
parameters or arguments).

In a normal function call, there will be one actual argument for each formal argument. Each actual
argument must be of the same data type as its corresponding formal argument. Remember that it is the
value of each actual argument that is transferred into the function and assigned into the corresponding
formal argument.

-There may be several different calls to the same function from various places within a program. The
actual arguments may differ from one function call to another. Within each function call however the
actual arguments must correspond to the formal arguments in the functions definition; i.e. the number
of actual arguments must be the same as the number of formal arguments and each actual argument
must be of the same data type as its corresponding formal argument.

Example 1: Factorial of an integer n

The factorial of a positive integer quantity n is defined as n! = 1 * 2 * 3 *…….* (n - 1) * n.


Thus, 2! = 1 * 2 = 2; 3! = 1 * 2 * 3 = 6; 4! = 1 * 2 * 3 * 4 = 24; and so on.

The function shown below calculates the factorial of a given positive integer n. The factorial is returned
as a long integer quantity, since factorials grow in magnitude very rapidly as n increases.

long int factorial (int n) /*Calculate the factorial of n */


{
int i;
long int prod = 1;
if (n >1 );
for(i =2; i <=n; i++)
prod * = i;
return(prod);
}

Notice the long int specification that is included in the first line of the function definition. The local
variable prod is declared to be a long integer within the function. It is assigned an initial value of 1
though its value is recalculated within a for loop. The final value of prod which is returned by the
function represents the desired value of n factorial (n!).

If the data type specified in the first line is inconsistent with the expression appearing in the return
statement, the compiler will attempt to convert the quantity represented by the expression to the data
type specified in the first line. This could result in a compilation error or it may involve a partial loss in
data (due to truncation). Inconsistency of this type should be avoided at all costs.

Example 2: Factorial of an integer n (return type not specified)


The following definition is identical to that in Example 1 except that the first line does not include a type
specification for the value that is returned by the function.

factorial (int n) /* calculate the factorial of n */


{
int i;
long int prod = 1;
if (n > 1)
for i =2; i < = n; i++)
return (prod);
}

The function expects to return an ordinary integer quantity since there is no explicit type
declaration in the first line of the function definition. However the quantity being returned is
declared as a long integer within the function. This inconsistency can result in an error (some
compilers will generate a diagnostic error and then stop without completing the compilation).
The problem can be avoided however by adding a long int type declaration to the first line of
the function definition as Example 1 shows.

The keyword void can be used as a type specifier when defining a function that does not return anything
or when the function definition does not include any arguments. The presence of this keyword is not
mandatory but it is good programming practice to make use of this feature.

Consider a function that accepts two integer quantities, determines the larger of the two and displays it
(the larger one). This function does not return anything to the calling portion. Therefore the function can
be written as;

void maximum (int x, int y)


{
int z;
z = (x >= y)? x : y;
printf(“\n \n maximum value = %d ” , z);
}
The keyword void added to the first line indicates that the function does not return anything.
FUNCTION EXAMPLES:
Void function
This is a function that does not return a value to the function. Their definition
starts with the word void:
e.g void OutputA()
{
Printf(“This is output A\n”);
}

#include <stdio.h>
//first function
Void OutputA()
{
Printf(“This is output A\n”);
}
//Second function
Void OutputB()
{
Printf(“This is output B\n”);
}

//The main function


Void main()
{
//Execute the above functions
OutputA();
OutputB();
}

Non-void function
This is a function that returns a value to the function call. They can be defined
using various data types like int.
e.g sqrt (x)

-User defined function

-Inbuilt function
Are functions that have been written and exist as library codes. They can be
directly interpreted by the compiler. The inbuilt functions are normally embodied
in certain header files e.g math.h
Examples include sqrt(x), sin(x), cos(x) and pow(x) these to write programs
Use

Example 4: Determining the maximum of two integers (Complete program)

The following program determines the largest of three integers quantities. The program makes use of a
function that determines the larger of two integer quantities. The overall strategy is to determine the
larger of the first two quantities and then compare the value with the third quantity. The largest
quantity is then displayed by the main part of the program.

/*Determine the largest of the three integer quantities*/


#include <stdio.h>
int maximum (int x, int y) /*Determine the larger of two quantities*/
{
int z;
z = (x > = y )? x : y;
return(z);
}
main()
{
int a , b , c ,d;
/*read the integer quantities*/
printf(“\n a = ”);
scanf(“%d”, &a);
printf(“\n b = ” );
scanf(“%d”, &b);
printf(“\n c = ”);
scanf(“%d”, &c);
/* Calculate and display the maximum value */
d = maximum (a, b);
printf (“\n \n maximum = % d ”, maximum (c ,d));
return 0;
}

The function maximum is accessed from two different places in main. In the first call to maximum, the
actual arguments are the variables a and b whereas in the second call, the arguments are c and d. (d is a
temporary variable representing the maximum value of a and b).

Note the two statements in main that access maximum, i.e.


d = maximum (a, b);
printf(“ \n \n maximum = %d ”, maximum (c, d));

A single statement can replace these two statements, for example:


printf (“ \n\n maximum = %d ” maximum(c, maximum (a, b)));

In this statement, we see that one of the calls to maximum is an argument for the other call. Thus the
calls are embedded one within the other and the intermediary variable d is not required. Such
embedded functions calls are permissible though their logic may be unclear. Hence they should
generally be avoided by beginning programmers.

Function Prototypes
In the previous function examples, the programmer -defined function has always preceded main. Thus
when the programs are compiled, the programmer-defined function will have been defined before the
first function access. However many programmers prefer a top down approach in which main appears
ahead of the programmer-defined function definition. In such a situation, the function access (within
main) will precede the function definition. This can be confusing to the compiler unless the compiler is
first alerted to the fact that the function being accessed will be defined later in the program. A function
prototype is used for this purpose

Function prototypes are usually written at the beginning of a program ahead of any programmer-
defined function (including main) .
The general form of a function prototype is;
data_type function_name (type 1 argument 1, type 2 argument 2, ., type n argument n);

Where data_type represents the type of the item that is returned by the function, function_name
represents the name of the function, type 1, type 2, … …., type n represent the types of the arguments 1
to n.

Note that a function prototype resembles the first line of a function definition (although a
definition prototype ends with a semicolon).
Function prototypes are not a must but are desirable however because they further facilitate error
checking between the calls to a function and the corresponding function definition.

The names of the argument within the function prototype need not be declared else where in the
program since these are “dummy” argument names that are recognised only within the prototype. In
fact, the argument names can be omitted (though it is not a good idea to do so). However the
arguments data types are essential.

In practice, the argument names usually included are often the same as the names of the actual
arguments appearing in one of the function calls. The data types of the actual arguments must conform
to the data types of the arguments within the prototype.

Function prototypes are not mandatory in C. They are desirable however because they further facilitate
error checking between the calls to a function and the corresponding function definition.

Example 6: Factorial of an integer n

Here is a complete program to calculate the factorial of a positive integer quantity. The program utilises
the function factorial defined in example 1 and 2. Note that the function definition precedes main.

1. /*Calculate the factorial of an integer quantity*/


#include <stdio.h>
long int factorial (int n);
main()
{
int n;
/* read in the integer quantity */
printf (“\n n = “);
scanf (“%d “, &n);
/* Calculate and display the factorial*/
printf (“\n n =%\d”, factorial (n));
return 0;
}
/*Calculate the factorial of n*/
long int factorial (int n)
{
int i;
long int prod=1;
if (n >1)
for( i=2; i<=n; i ++)
prod *= i;
return (prod);
}
1. //a program to calc the square of a number using a fn prototype

#include <stdio.h>
int square(int n);
main()
{
int n, s;
/* read in the integer quantity */
printf (“Enter n value\n “);
scanf (“%d “, &n);
/* calculate and display the square*/
S=square (n);
printf (“\n the square of n = %d”, s);
return 0;
}
/*Calculate the square of n*/
int square (int n)
{
int sqr;
sqr=n*n;
return (sqr);
}

The programmer-defined function makes use of an integer argument (n) and two local variables (an
ordinary integer and a long integer). Since the function returns a long integer, the type declaration long
int appears in the first line of the function definition.

Parameter Passing in C Functions


Parameter passing is the mechanism used to pass parameters to a procedure
(subroutine) or function.
The most common methods are to pass the value of the actual parameter (call by
value), or to pass the address of the memory location where the actual parameter
is stored (call by reference). The passing by reference allows the procedure to
change the value of the parameter, whereas the former method guarantees that
the procedure will not change the value of the parameter.

There are various types of parameter passing techniques available in programming languages
later displayed below. These are based on how actually parameter is passed to called function
(Function which is called) from calling function (Function which calls the other function also
called Caller function). Given the program below:

float square ( float ) ;


main( )
{
float a, b ;
printf ( "\nEnter any number " ) ;
scanf ( "%f", &a ) ;
b = square ( a ) ;
printf ( "\nSquare of %f is %f", a, b ) ;
}
float square ( float x )
{
float y ;
y=x*x;
return ( y ) ;
}

In above program main() calls the square() so main() is caller function and square() is called
function.

1. Call by value Parameter passing technique


When we call the function, we pass parameter to called function and it is by default passed by
the value of variable in calling function. The passing by value guarantees that the procedure will
not change the value of the parameter. Generally we use call by value mechanism if we don’t
need the changes made in calling function to reflect in called function. E.g.

/* Call by value Parameter passing technique */


int calsum (int x, int y , int z ) ;
main( )
{
int a, b, c, sum ;
printf ( "\nEnter any three numbers " ) ;
scanf ( "%d %d %d", &a, &b, &c ) ;
sum = calsum ( a, b, c ) ;
printf ( "\nSum = %d", sum ) ;
}
calsum (int x, int y, int z )
{
int d ;
d=x+y+z;
return ( d ) ;
}

If we give input 20,30,40, then output will be sum=90.The value of variable a,b,c in main are
20,30,40 on calling function calsum(a,b,c) as we are passing their values to variable x,y,z
respectively. So value of variable x,y,z in function calsum() after is also 20,30,40 respectively.

/* Call by value Parameter passing technique */


Void exchange ( int x, int y );
main( )
{
int a = 10, b = 20 ;
printf ( "\na = %d b = %d", a, b ) ;
exchange( a, b ) ;
printf ( "\na = %d b = %d", a, b ) ;
}
exchange ( int x, int y )
{
int t ;
t=x;
x=y;
y=t;
printf ( "\nx = %d y = %d", x, y ) ;
}

Before calling exchange() value of a,b are 10,20 respectively. After calling exchange() x,y also
receives 10,20 respectively . In exchange() we are interchanging value of x,y, So new value of
x,y are 20 ,10 respectively. After successful execution of function exchange() control transfer to
main function but in main function value of a,b remain unchanged i.e. 10,20 respectively.

So output of above program is


a=10 b=20
x=20 y=10
a=10 b=20

2. Call by reference Parameter passing technique

This type of parameter passing technique is also called as call by address because we are passing
the address of actual variable as an argument to called function instead of value of actual
argument. Each variable has some fixed address which remains constant throughout execution of
program in memory. Using this address of variable, it is also possible to access and modify the
value of variable by using pointer. But if we required the changes to reflect in called function we
use call by reference mechanism.

Consider declaration of variable..


int x= 10; this tells the compiler:
1) to allocate 2 byte (depending on type of compiler and type of variable ) memory location
on stack frame of that particular function in which it is declared.
2) to hold value of type integer and also associate this address with name x and
3) this memory location is initialized with value 3.
Memory Map

Selection of address for particular variable is compiler dependent and is always whole number.
We can access value 10 by using variable name x in this case and by address 65530 also.
‘&’ is a special operator in c used as ‘address of’.
Eg The expression &x in above case return address of variable x which happens to be 65530. As
address is always positive, we use operator %u for unsigned integer.
‘*’ is special operator in c used as ‘value at address’ also called indirection operator.
E.g. *(&x) which means value at address (&x) i.e. value at address (65530) which happens to be
value of variable x=30.

/* Call by Reference Parameter passing technique */

#include <stdio.h>

Void main( )
{
int x = 10;
printf ( "\nAddress of x = %u", &x ) ;
printf ( "\nValue of x = %d", x ) ;
printf ( "\nValue of x = %d", *( &x ) ) ;
}

Output of program is
Address of x = 65530
Value of x = 10
Value of x = 10

In call by reference we pass the address of actual parameter in calling function and is copied in
formal argument in called function .As we are passing address of actual parameter, changes
made to formal argument would reflect in calling function.

/* Call by Reference Parameter passing technique */

#include<stdio.h>

Void exchange (a,b);

void main( )
{
int a = 10, b = 20 ;
printf ( "\na = %d b = %d", a, b ) ;
exchange( &a, &b ) ;
printf ( "\na = %d b = %d", a, b ) ;
}

void exchange( int *x, int *y )


{
int t ;
t = *x ;
*x = *y ;
*y = t ;
}

The output of above program is

a = 10 b = 20
a = 20 b = 10

Consider declaration of variable


int *x= 10; which means x is declared as pointer variables, i.e. variable is capable of holding
address which is always positive whole number.
int * x does not mean that x is going to hold integer value rather it simply means it is going to
hold address (memory location ) of integer type of variable.
We are passing address of variables a, b to function exchange () so while receiving we are using
two pointer to integer.

The Scope of Variables


Local variables:
Variable whose existence is known only to the main program or functions are called local
variables. Local variables are declared with in the main program or a function.

Global variables:
Variables whose existence is known to the both main() as well as other functions are called
global variables. Global variables are declared outside the main() and other functions.
The following Program illustrates the concept of both local as well as global variables.

Statement of C Program: This program does not accept anything from the keyboard. It
initialises the variables a to 10 outside the main() function and value().

#include<stdio.h>
int a = 10; /* global declaration */
main()
{
int b;
printf(" = %d\n" , i);
b = value(i)
printf(" j = %d\n");
} /* End of main() */
/* Function to compute value */
int value(i)
int i;
{
int c;
c = i + 10;
return(c);
} /* End of Function */

Explanation:
The statement int i = 10; that appears before the main() is a global declaration. The value of i
is accessed by the main program as well as the function value(). The variable c is local to the
function value(). It has no existence in the function value(). The variable b is also local to the
main() but has no scope in the function value().

Recursion
Recursion is the process by which a function calls itself repeatedly until a special condition is
satisfied.

To use recursion, two conditions must be satisfied:


(i) The problem must be written in a recursive form.
(ii) There must be a stopping case (terminating condition).

Example

The factorial of any possible integer can be expressed as;


n ! =n * (n-1) * (n-2) *………* 1.
e.g. 5 ! = 5 * 4 * 3 * 2 * 1.

However we can rewrite the expression as; 5! = 5 * 4!

Or generally,

n! = n * (n –1)! (Recursive statement)

This is to say that in the factorial example, the calculation of n is expressed in form of a previous result
(condition (i) is satisfied).

Secondly 1! = 1 by definition, therefore condition (ii) is satisfied.

Example: factorial in recursive form


#include<stdio.h>
long int factorial (int n); /*factorial function prototype*/
main()
{
int n;
/*Read in the integer quantity*/
printf (“n = ” );
scanf (“%d ”, &n);
/*Calculate and display the factorial*/
printf (“n! =%d \n”, factorial (n));
return 0;
}
/* Function definition */
long int factorial (int n)
{
if (n <=1) /*terminating condition*/
return (1);
else
return (n * factorial (n-1));
}
The functional factorial calls itself recursively with an actual argument that decreases in magnitude for
each successive call. The recursive call terminates when the value of the actual argument becomes equal
to 1.

Revision Exercises
Explain the meaning of each of the following function prototypes
(i) int f(int a);
(ii) void f(long a, short b, unsigned c);
(iii) char f(void);
2. Each of the following is the first line of a function definition. Explain the meaning of each.
(i) float f(float a, float b)
(ii) long f(long a)
3. Write appropriate function prototypes for each of the following skeletal outlines shown below.
(a) main()
{
int a, b, c;
……
c =function1(a,b);
……
}
int fucntion1(int x, int y)
{
int z;
……
z = ……
return(z);
}
(b) main()
{
int a;
float b;
long int c;
……
c = funct1(a,b);
……
}
int func1(int x, float y)
{
long int z;
……
……
z = ……
return (z);
}
4. Describe the output generated by the followed program.

#include<stdio.h>
int func(int count);
main()
{
int a,count;
for (count=1; count< = 10; count + +)
{
a = func(count);
printf(“%d”,a);
}
return 0;
}
int func(int x)
{
int y;
y = x * x;
return(y);
}
5. (a) What is a recursive function?.
(b) State two conditions that must be satisfied in order to solve a problem using recursion.

You might also like