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

Functions are building blocks of a C

Uploaded by

deju
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

Functions are building blocks of a C

Uploaded by

deju
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 14

Functions are building blocks of a C++ programs.

Basically functions are subprograms,


which perform well-defined tasks and can be invoked from other parts of the program.
As stated earlier the execution of every C++ program starts from main() function and
also ends from main() function. It is the main() function which calls other functions, each
of which returns to the main() functions. And these other functions do call lower level
functions. Therefore when a function calls another function, its execution would not be
completed until the called function returns.

Each function is developed separately and tested. Basically there are two types of
functions.
1. Built–in functions
2. User–defined functions

Built–in functions are those functions, which are provided by the C++ language and
are coded into machine language.

User–defined functions are those functions, which are written by the programmer for
its sake of convenience. It is the programmer who names each such function and
specifies the method of sending the data and getting the results from them.

The most important reason to use function is to aid in conceptual organization of a


program. It is basically a structured programming concept of dividing a program into
functions. Another reason to use functions is that each function is easily
understandable. Functions also save memory space because they are stored in only
one place even though they are executed many times in a program. Let us begin the
discussion with a simple function.

Simple Functions
A function definition has a function header & a function body. The function header has
three parts:
- Function name
- A parameter list
- A return type

Each function is represented by its name. The function operates on its parameters
(arguments), if specified. If there are more than one parameter then they are separated
by a comma. The function’s parameter list is enclosed in parentheses. The result of a
function is reflected through its return value, referred as the function return type. The
return value is any valid C++ data types, either built-in or user-defined. If a function
does not return any value then it has a return type of void. The parameter list is
preceded by the function body, which is enclosed in braces. The function body is
sometimes referred to as the function block. This complete set of function return type,
name of the function, the parameter list and the function body is called to be the
function definition.
Here is the simple program that illustrates the concept of using simple function.
// Program – 1.cpp
#include
void example(); // Function Declaration
void main ()
{
cout << “\n I am in function main”;
example(); // Function Call
cout << “\n I am back in function main”;
}
void example() // Function Definition
{
cout << “\n I am in function example”;
}

The output of this program is as:


I am in function main
I am in function example
I am back in function main

From this program, it is cleared that three features are needed to use user-defined
functions:
1) Function declaration
2) Function call
3) Function definition

1) Function Declaration:
We know that we can not use a variable without declaring it. Likewise we can’t use a
function until we declare it at the beginning of the program. Although K & R’s C did not
have that requirement but C++ has a strong type checking built into the language
definition. Thus in C++ you must tell the compiler the number and the types of the list of
arguments (parameters) and its return value; otherwise a compile time error results. The
function declaration consists of the return type, the name of the function, and the list of
arguments.

Function declaration is also referred as function prototype. The syntax of function


declaration is as:

return_type function_name(list_of_arguments);

In program 1 the function declaration of example () function is as:

void example();
Actually you can say that a function declaration describes the kind of information the
function must receive (list of arguments) and the kind of information it returns back, if
necessary. If the function has no return value we will use void keyword. We can not call
such function in the context of an expression where it is expected to return a value. For
example, we can not call a void function from the right side of an assignment statement.
K & R’s C did not have void function. In C, if you do not specify the return value of a
function in its declaration, it was assumed to return an int.

If it takes no argument then parenthesis must be empty. We can also use a void
keyword in parenthesis to indicate that the function takes no argument as:

void example (void);

The return type of a function can be a built-in data type, such as an int or a float or any
user-defined data types, such as struct or class, etc. Here are some more examples of
possible return types:

double average(double, double, double);


int reverse(int);

You can also specify parameter names in the list of arguments. A parameter name is
just a documentation aid that allows the parameter to be accessed from within the body
of the function such as:

double average(double x, double y, double z);


int reverse(int n);

However some programmers prefer to omit the identifier in the list of arguments
whereas others prefer to assign meaningful parameter identifiers in the prototype
declaration. Note that no two-parameter names appearing in the list of arguments can
be same as:

double average(double x, double x, double z);

Let we have used a function complex that receives two variables of type int and its
return type is also an int then its function declaration will be as:

int complex (int, int);

2) Function Call:
The function is called by its name, followed by parenthesis as:

example();

And the syntax of calling any function is as:


function_name (list_of_arguments);

The syntax of function calling is similar to that of declaration except that the return type
is not used. Like function prototype, the function call also is terminated by semicolon.
When the program is executed and it encounters a function call, it immediately transfers
the control to the called function. Therefore firstly that function would get completed and
then control would return to the statement follows the function call.

3) Function Definition:
Function definition contains the actual code for the function. The syntax of function
definition is as:
return_data_type function_name(list_of_arguments)
{
// Declaration of local variables
// Function body
}

The first statement

return_data_type function_name (list_of_arguments)

must agree with its declaration – the same function name, the same number of
arguments in same order and the same return type. When the function is called, the
control is transferred to the first statement in function body. The other statements of the
function body are then executed and when the closing braces is encountered, control
returns to the calling program. In program 1 the function definition is as:

void example()
{
cout << endl << “I am in function example”;
}

As stated earlier that C++ is a strongly typed language. The arguments of every function
call are type-checked during the compilation process. If the types of the arguments
specified in the list of arguments in function declaration do not match then an implicit
conversion is applied, if possible, such as conversion of a float to an int. Let you have a
function declaration as:

int sum(int, int);

This declaration that the function sum() is receiving two arguments of type ints. Thus
when we call this function as:

sum(240);
Or what happens if sum() is passed more than two arguments as:

sum(2, 4, 6);

Here the compiler would certainly flag a compile-time error. But if the arguments are of
type floats as:

sum(2.0, 4.0);

Then the value of type float can be converted to a value of type int implicitly. In this case
the compiler would not flag any error, rather than it just displays a warning message. If
an implicit conversion is not possible or the number of arguments does not match, a
compile-time error would be certainly issued by the compiler. And this is the main
reason that a function can not be called until it has been first declared.

Call by Address
In call by address, instead of passing the actual values of the actual argument we pass addresses of
actual values. Whenever we deal with addresses, we must know how to handle them. That’s why before
discussing call by address, we will briefly discuss pointers that handle addresses.

Introduction to Pointers

We all know that the internal data storage of a computer is a memory unit. Memory unit is an
ordered sequence of memory cells, each capable of containing a piece of data. Each memory cell
has a distinct address that can be used to refer to it when data is stored in it or retrieved from it.

The addresses of memory depend upon its capacity. For a 640 KB of memory we have addresses
from 0 to 655,359; for 1 MB of memory we have addresses from 0 to 1,048,575 & so on. Since
the memory holds data and instructions, therefore when our program is loaded into memory it
occupies some space in memory. It means that every variable and every function starts at a
particular address.
//Program–8.cpp
#include
Void main()
{
int i=4, j=8;
cout<< i << j;
}
Here the addresses of variable i and j are 62800 and 62802 respectively. And the value 4 and 8
are stored at the addresses 62800 and 62802 respectively. Program 9.cpp illustrates this concept.
// Program –9.cpp
#include
void main()
{
int i=4, j=8;
cout << “\n Value=”<< i << “\tAddress=”<< &i;
cout << “\n Value=”<< j << “\tAddress=”<< &j;
}

The output of this program is:


Value = 4 Address = 0x8facfff4
Value = 8 Address = 0x8facfff2

The output represents the addresses in hexadecimal form, as indicated by the prefix 0x before
each address. One main point to note that their addresses may vary during particularly in multi
user computer system.

Pointer Declaration :
As we store integer values into integer variables, we can also store addresses of variables in a
special type of variables, known as pointer variables. Thus a pointer variable is defined as the
variable that holds an address of a memory location. The syntax of the declaration pointer
variable is

datatype * pointer_var_name;

The datatype is any valid C++ data type and pointer_var_name is the name of the pointer
variable name. Here the asterisk (*) operator implies pointer to. The result of pointer operator, *,
does the reverse of address operator &. It means that the pointer operator (*) returns the value of
variable stored at the address following it. Thus to access the value stored at any address we will
use pointer operator. Program 10.cpp illustrates this concept:

// Program – 10.cpp
#include
void main()
{
int i=4;
int *iptr;
iptr = &i;
cout << “\n Value = ”<< i << “\tAddress = ”<< &i;
cout << “\n Value = ” << *iptr << “\tAddress = ” <
}

The output of this program is as:


Value = 4 Address = 0x8facfff4
Value = 4 Address = 0x8facfff4

In this program, the statement

int *iptr;
means that iptr is a pointer variable that contains an address of variable type int, in other words
iptr acts as a pointer to integer. Thus if iptr contains an address then *(iptr) contains a value
stored at this address.

That is why in this program

*(iptr) results in 4.

Like integer pointer we can also have pointers for other data type such as char, float or even for a
user defined data type as:

char *cptr;
float *fptr;
long *lptr;

Like ordinary variables, we can also define multiple pointers in one line as:

int *iptr1, *iptr2, *iptr3;

While using pointer variables one should remember that we store the address of a data type into
the pointer of same data type. We can not store the address of a variable of one type into another
type of pointer variable. It means that integer pointer can hold an address of integer variable,
float pointer can hold an address of float variable and so on.

Now we will see how to use pointers in call by address functions. In cal by address we pass
addresses of actual arguments to the called function. These addresses are stored into formal
arguments, which are nothing other than pointer variables. Now whatever changes are made into
the formal arguments they are directly reflected to the actual arguments..

// Program –11.cpp – Call by address


#include
void swapadd (int *, int *);
void main ()
{

int a, b ;
cout << "\nEnter two numbers = " ;
cin >> a >> b;
cout << "Before calling swapadd() function.";
cout << "\na = " << a;
cout << "\nb = " << b;
swapadd (&a, &b ) ;
cout << "\nAfter calling swapadd() function.";
cout << "\na = " << a;
cout << "\nb = " << b ;
}
void swapadd(int *aa, int *bb)
{
int temp;
temp = (*aa);
(*aa) = (*bb);
(*bb) = temp;
}

In program 11.cpp, we pass the addresses of variables a and b to the functions swapadd(). When
the function swapadd() is invoked, the addresses of a and b are copied into the integer pointers aa
and bb respectively.

Here is the output of this program….


Enter two number = 10 20
Before calling swapadd() function.
a = 10
b = 20
After calling swapadd() function.
a = 20
b = 10

Call by Reference
In call by reference, a function passes a reference as an argument to another function. In this case
the called function works on the callers copy of parameters and not on a local copy. Before the
discussion of call by reference we must know what is a reference.

Introduction to Reference
A reference is referred to as an alias or synonym, that is an alternate name for another variable.
Like pointers, the reference enables us to pass large amount of data without the overhead of
copying them. Of course pointer also is an important feature of C and C++, but sometimes it may
trouble you and even a good programmer for some complex operations.

References are much like pointers. You can do anything with a reference that you can do with a
pointer. The C++ reference variables can give you same type of problem until you understand
them. However it has certainly some plus points over pointers.

A reference is indicated following the type specifier with the address-of & operator or you can
say the & operator identifies a reference variable. A reference must be initialized when it is
declared as in the following example:

int a=10;
int &b = a;

Here we have declared an integer variable, a, that has another name, b. Note that a reference can
not be made to refer to another variable (this is why it must be initialized. If you make any
change to a reference then that change is actually applied to the variable to which the reference
refers. Therefore now all references to either name have the same effect.

For example,

b+= 5;

adds 5 to a, the variable referred to by b. Another main point to note that each definition of a
reference must be preceded by the address of operator. For example,

int &x = a, y = b;

defines one reference and one variable. Let us take a simple example that illustrates the concept
of a reference:

// Program – 12.cpp – Use of reference


#include
void main()
{
int a = 20 ;
int & b = a;
cout << “\n a = “ << a << “ b = “ << b ;
b = 40;
cout << “\n a = “ << a << “ b = “ << b ;
a = 60;
cout << “\n a = “ << a << “ b = “ << b ;
}

The output of this program is


a = 20 b = 20
a = 40 b = 40
a = 60 b = 60

In this program b is called as reference to a. From the above program we see that a variable and
its reference are so closely inter–linked that if one changes then another will automatically
change. And remember that even the address of a and b are same.
From this output, it is clear that a reference is neither a copy nor a pointer to the object to which
it refers. Instead it is just like another name. However you can verify this by executing program
13.cpp.

// Program – 13.cpp
#include
void main()
{
int a = 20 ;
int & b = a;
cout << “\n a = “ << a << “ Address of a = “ << &a ;
cout << “\n b = “ << b << “ Address of b = “ << &b ;
}

The output of this program is


a = 20 Address of a = Ox8facfff420
b = 20 Address of b = Ox8facfff420

Thus the two addresses are same.

There is a subtle difference between a normal reference and a const reference. A const reference
can be initialized to a variable of a different data type; obviously there is a conversion from one
type to another, as well as to some constants. For example,

float x = 25.75;
const int & a = x;
const int & b = x+10;
const int & c = 204;

These above initializations are completely invalid for non-const references and thus they result in
compile-time errors. When is initialized to a variable type then the compiler must generate a
temporary object that the reference actually address but unfortunately user has no access to it.
Thus the following two statements:

float x = 25.75;
const int & a = x;

are internally transformed as:

float x = 25.75;
int temp = x;
const int &a = temp;

Also the statement

const int &c = 204;

is also interpreted as:

int temp = 204;


const int &c = temp;

Now we see how it helps in function swapref().

// Program – 14.cpp: Call by reference


#include
void swapref(int &, int &);
void main()
{
int a, b;
cout << “\nEnter two numbers = ” ;
cin >> a >> b ;
cout << "Before calling swapref() function.";
cout << “\na = ”<< a << “\tb = ”<< b;
swapref(a, b);
cout << "After calling swapref() function.";
cout << “\na = ” << a << “\tb = ” << b;
}
void swapref(int &aa, int &bb)
{
int temp;
temp = aa;
aa = bb;
bb = temp;
}

The output of this program is:


Enter two numbers = 5 10
Before calling swapref() function.
a = 5 b = 10
After calling swapref() function.";
a = 10 b = 5

Naturally the above program looks very simple and convenient way than call by address.

The const Reference :


In program 14.cpp, the swapref() function modifies the caller’s variables because the parameters
are references to those variables. However in certain situations, a function is restricted to modify
caller’s referenced variable. To handle this, we declare such arguments as const.

The const reference arguments ensures the caller that the called function can view them but can
not modify the values in the referenced arguments. The const references are treated as read only
arguments. In program 14.cpp if you use the following reference function.

void swapref(const int &aa, const int &bb)


{
int temp;
aa = temp;
aa = bb;
bb = temp;
}

You would certainly get an error message, say:


Can not a const object

Returning a Reference

We have already studied that how to pass a reference to a function as a parameter. However you
also can return a reference from a function. In such cases when a function returns a reference the
function call can exist in any context in which a reference can exist, including on the receiving
side of an assignment. Program 15.cpp illustrates this concept.

// Program - 15.cpp
#include
int &max(int &, int &);
void main()
{
int x, y;
cout<<”\n Enter any two numbers = ”;
cin >> x >> y;
int &z=max(x, y);

cout<<”\nLargest number is “< }


int & max(int &a, int &b)
{
if (a>b)
return a;
else
return b;
}

In this program, the program declares an int reference named z and initialize the reference with
the reference returned by the max() function/

When you execute this program, you get the following output:
Enter any two numbers = 10 15
Largest number is 15

Default Functions Arguments


In earlier programs we have discussed such programs that receives same number of arguments as
they are provided to it. That is if we pass three arguments then the called function must receive
three arguments in three formal variables. C++ provides a facility to define initial values for
arguments that are not passed when the function is called.

A C++ function prototype can declare that one or more of the function’s argument have default
argument values for arguments in a C++ prototype like this

int add(int a=10, int b=20, int c=30);


Now when a call to the function does not contain the corresponding arguments, the compiler
inserts the default values where it expects to see the arguments. Let us understand this concept of
default arguments by examining program 16.cpp

// Program – 16.cpp: Default arguments


#include
int add(int a = 10, int b = 20, int c = 30);
void main ()
{
int aa, bb, cc, dd;
cout << “\nEnter three numbers = ” ;
cin >> aa >> bb >> cc;
dd = add(aa, bb, cc);
cout << “\nThe addition of three numbers = ” << dd ;
dd = add(aa, bb);
cout << “\nThe addition of three numbers = ” << dd ;
dd = add (bb, cc ) ;
cout << “\nThe addition of three numbers = ” << dd ;
dd = add (cc, aa) ;
cout << “\nThe addition of three numbers = ” << dd ;
dd = add (aa);
cout << “\nThe addition of three numbers = ” << dd ;
dd = add (bb);
cout << “\nThe addition of three numbers = ” << dd ;
dd = add (cc);
cout << “\nThe addition of three numbers = ” << dd ;
dd = add();
cout << “\nThe addition of three numbers = ” << dd ;
}

int add(int a, int b, int c)


{
return (a + b + c);
}

The output of this program is

Enter three numbers = 100 200 300


The addition of three numbers = 600
The addition of three numbers = 330
The addition of three numbers = 530
The addition of three numbers = 430
The addition of three numbers = 150
The addition of three numbers = 250
The addition of three numbers = 350
The addition of three numbers = 60

Now let us examine the output of program 16.cpp. When we call the function add() with three
arguments, say add(aa, bb, cc), then the formal arguments are replaced with actual arguments aa,
bb and cc. When second call statement add (aa, bb) is executed, the first and second formal
arguments are replaced with actual arguments and the third formal arguments uses default value,
which is 30, that’s why second statements results in 330. Now in third statements you will think
that we pass the values of bb and cc and in called function they are stored in b and c respectively
and the third argument, which is default, is a.

So you expect the output to be 510. But this is wrong, because the values of bb and cc are stored
in a and b respectively and the missing argument is assumed to be the last argument which is c in
our program 10. That’s why its output is 530. The forth statement also outputs in the same way.
The fifth statement, add (aa), passes just one argument thus two argumen ts are to be default.

Thus in default arguments case, we will have to remember two main points:

- Default values are always been taken from trailing variables.


- Default values should be defined where we are defining the function prototype and should not
be repeated in function definition.

You might also like