Sie sind auf Seite 1von 50

78 Procedure Oriented Programming Using C

4.1.1. Introduction
> Every C program consists of one or mors functions. On^ 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 main, and perhaps
to one another.
> Generally, a function will process information that is passed to it from the s. idling
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 (of type
void), whereas other functions return multiple values, with help of pointers and
arguments (e.g., library function scanf).

4.1.2. Purpose of Functions


> The use of functions allows managing large and complex problems by factoring
them into small, simple and manageable parts.
> The use of functions provides a way to reuse code that is required in more than one
place in a program.
> C language comes with a rich and valuable library. These C libraries provide
standard functions that make our work as a programmer much easier. Programmer
can also create our personal libraries that make developing new systems much
easier.
> The use of functions can protect data. This is done using the concept of local data.
Local data consist of data described in a function. This data is available only to the
function and only while the function is executing. When the function is not
executing, the data is not accessible. Data in one function, then, cannot be seen or
changed by another function.

4.1.3. Standard Functions


The functions that are inbuilt in the language compiler are library functions. For
example, printf() and scanf() belongs to the category of library functions.

The C language comprises a library of standard functions. Most versions of C provide


the libraries in both source code and re-locatable code. The re-locatable code is already
compiled into an intermediate code which is linked with the compiled main program to
form the final object code program.
These standard functions perform most of the commonly used operations or calculations
such as input/output operations (read and write characters), open and close files,
functions that perform operations on characters (conversion from lower case to
uppercase and vice versa), functions to carry-out mathematical calculations (finding
square roots, evaluate trigonometric expressions), functions that perform operations on
strings (comparing two strings, concatenating strings), etc. Table 4.1 show the some
library functions available in C language:
Table 4.1: Library Functions of C
Function Type Purpose Include
File
abs(i) int Returns the absolute value of i. stdlib.h
exit(u) void Closes all files and buffers and terminates the stdlib.h
program. |
fclose(f) int Closes file f. Returns 0 if the file is successfully stdio.h
closed.
fgete(f) int Enters a single character from file f. stdio.h
fgets(s, i, f) char Enter string s, containing i characters, from file f. stdio.h

fopen(sl, s2) FILE* Opens a file named si of s2 type. Returns a pointer stdio.h
to a file.
fprintf(f,...) int ’ Sends data items to file f. stdio.h
fputc(c, f) int Sends a single character to file f. stdio.h
fputs(s, f) int Sends string s to file f. stdio.h
fread(s, il, i2, f) int Inputs i2 data items each of size il bytes, from file stdio.h
f to string s.
free(p) void Frees a block of allocated memory whose starting Malloc.h or
address is indicated by p. stdlib.h
fscanf(f,...) int Inputs data items from file f. stdio.h
fseek(f, 1, i) int Moves the pointer for file f at distance 1 bytes stdio.h
from location i (i may represent pointer position or
end-of-file).
pow(dl, d2) double Returns dl raised to the power d2. math.h
printf(...) int Sends data items to the standard output device. stdio.h

putchar(c) int Sends a single character to the output device. stdio.h


puts(s) int Sends the string a to the standard output device. stdio.h

scanf(....) int Allows input of data items from the standard ouput stdio.h
device.
strcmp(sl, s2) int Compares two strings. Returns a -ve value if si < string .h
s2,0 if si = s2, +ve if si > s2.
strcpy(sl, s2) char* Copies string s2 to string si. string.h
strlen(s) int Returns the number of characters in string s. string.h
toascii(c) int Converts value of argument to ASCII. ctype.h
tolower(c) int Converts value of argument to lower-case. ctype.h or
stdlib.h
toupper(c) int Converts letter to upper-case. ctype.h or
stdlib.h
To use the standard library functions, one has to include certain specific information,
within the main portion of the program. This type of information is stored in special
files. These special files are accessed with the preprocessor statement #include and
followed by the filename as shown below: #include<filename>

These special files are generally supplied with the compiler. The commonly used
filenames are stdio.h, stdlib.h, etc. The suffix “h” denotes a “header” file. This file has to
be included at the beginning of the program.

4.1.4. User-Defined Functions


These are actually the user modules that are deliberately created for a specific purpose.
This creation of modules results in function. Various programming constructs like
looping, jumping are used with it.

The main difference between built-in and user-define functions is that library functions
are not required to be written by us whereas a user-defined function has to be developed
by the user at the time of writing a program.

However, a user-defined function can later become a part of the C program library.
Need for User-defined Functions
There are times when certain operation or calculations are to be repeated during a
program. For example, we may use a factorial of a number or printing some string lines
in the program. In these situations we may repeat the code in our program or just copy-
paste it. That’s why we make these user-defined functions and use it whenever
necessary. Here, user-defined functions can be really helpful and can save the time and
program space.

4.1.5. Function Definition


The general form of a function definition in C programming language is as follows:
Syntax:
return_type function_name(parameter list)
{
body of the function
}

A function definition in C programming language consists of a function header and a


function body. Here are all the parts of a function:
1) Return Type: A function may return a value. The return_type is the data type of
the value the function returns. Some functions perform the desired operations
without returning a value. In this case, the retumjype is the key word void,
2) Function Name: This is the actual name of the function. The function name and the
parameter list together constitute the function signature.
3) Parameters: A parameter is like a placeholder. When a function is invoked, you
pass a value to the parameter. This value is referred to as actual parameter or
argument. The parameter list refers to the type, order, and number of the parameters
of a function. Parameters are optional; i.e., a function may contain no parameters.
4) Function Body: The function body contains a collection of statements that define
what the function does.
For example, Following is the source code for a function called max(). This function
takes two parameters num l and num 2 and returns the maximum between the two:
/* function returning the max between two numbers */
int max(int numl, int num2)
{
/* local variable declaration */
int result;
if(numl>num2)
result = numl;
else
result = num2;
return result;
}
Rules for Defining Functions
1) The first statement of the function must be the function defining statement
specifying the return type, name and formal arguments.
2) If the type of the function is omitted, then it is assumed of type integer (int). But it
is recommended that the return type must be explicitly specified.
3) Rules for naming a function are same as for variable names.
4) The formal arguments should neither be constants or expressions.
5) If a formal argument is an array name, it must be declared as an array in a type
declaration statement before the body of the function starts and its maximum size
must be equal to the actual size in the calling function.

4.1.6. Function Declaration


A function declaration statement is also known as prototype of the function or as
function prototype. Function declaration consists only of a function header; it contains
no code. Function header consists of three parts:
Syntax:
return_type Function_name(argument list);

1) Return_Type: If the function has no arguments, then write void in the parentheses,
else the specific return type is mentioned. If the function has two or more
arguments, each is separated by comma.
2) Function_Name: It is given by the programmer as in case of variables.
3) Argument List: It is not mandatory (essential) to include the names of the
arguments in the argument list. The purpose of the argument list is to tell the
compiler the number, data type and order of arguments. The names of arguments
do not need to be the same in the function declaration and the function definition.
On the other hand, if the data types do not match, the compiler will flag an error.
The compiler checks the data types of the arguments in the function call to ensure
that they are the same or at least compatibility.
A semicolon follows the function header. Function declarations also provide an
excellent quick reference for functions used in the program, making them excellent
documentation.
For example,
int largest(int a, int b, int c);

Explanation: Above function definition tells the compiler that the return type of the
function is int, name of the function is largest, and it has three arguments, all of type
int. The names of argument are not significant.

4.1.6.1. Rules for Declaring a Function


1) The parameter list must be separated by commas.
2) The parameter names do not need to be the same in the prototype declaration and
the function definition.
3) The types must match the types of parameters in the function definition, in number
and order. ’
4) Use of parameter names in the declaration is optional.
5) If the function has no formal parameters, the list is written as (void).
6) The return type is optional, when the function returns int type data.
7) The retype must be void if no value is returned.
8) When the declared types do not match with the types in the function definition,
compiler will produce an error.

4.1.6.2. Location of Declaration in Program


The place of declaration of a function defines a region in a program in which the
function may be used by other functions. This region is known as the scope of the
function.
A prototype declaration may be placed in two places in a program:

1) Above All Functions (Global Prototype): It also includes main(). When we place
the declaration above all the functions (in the global declaration section), the
prototype is referred to as a global prototype. Such declarations are available for all
the functions in the program.
2) Inside Function Definition (Local Prototype): When we place it in a function
definition (in the local declaration section), the prototype is called a local
prototype. Such declarations are primarily used by the functions containing them.

It is a good programming style to declare prototypes in the global declaration section


before main. It adds flexibility, provides an excellent quick reference to the functions
used in the program, and enhances documentation.

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.
4.1.7. Function Arguments
Basically there are two types of function arguments in c:

4.I.7.I. Actual Arguments


Sometimes a function may be called by a portion of a program with some parameters
and these parameters are known as the actual arguments.

For example,
main()
{
int x, y;

------------

-----------

output(x, y); /* x and y are the actual arguments */

}
4.I.7.2. Formal Arguments
The formal arguments are those parameters present in a function definition and it
may also be called as dummy arguments or the parametric variables.

For example,
main()
{
int x, y;

-------

-------

output(x, y);
}
output(a,b) */ formal or dummy arguments */
int a, b;
{
/* body of the function */
}
The formal arguments may be declared by the same name or different in calling a
portion of the program and a called function but the data types should be same in
both blocks.

For example, the following function declaration is invalid:


main()
{
int x, y;

char s1, s2

---------

--------

function(x, y, si, s2);


}
function (x, y, s1, s2)/* data type mismatch */
char x, y;
int s1, s2;
{
/* body of a function */
}

4.1.8. Function Call


> A function can be accessed (i.e., called) by specifying its name, followed by a
list of arguments enclosed in parentheses and separated by commas.
> The function call may be a part of a simple expression (such as an assignment
statement), or it may be one of the operands within a more complex expression.
> A function call is a postfix expression. The operator (.) is at a very high level of
precedence. Therefore, when a function call is used as a part of an expression, it
will be evaluated first, unless parentheses are used to change the order of
precedence.
> In a function call, the function name is the operand and the parentheses set (.)
which contains the actual parameters is the operator. The actual parameters must
match the function’s formal parameters in type, order and number. Multiple
actual parameters must be separated by commas.
Note:
i) If the actual parameters are more than the formal parameters, the extra actual
arguments will be discarded.
ii) On the other hand, if the actuals are less than the formals, the unmatched
formal arguments will be initialized to some garbage.
iii) Any mismatch in data types may also result in some garbage values.
Argument Conversions
When a function is called, there are a number of possible conversions that will be
applied to the values supplied as arguments depending on the presence or absence of a
prototype.

The rules mention the default argument promotions and compatible type. Where they
are used, the default argument promotions are:
1) Apply the integral promotions to the value of each argument,
2) If the type of the argument is float it is converted to double.

Rules for Conversion


1) At the point of calling a function, if no prototype is in scope, the arguments all
undergo the default argument promotions. Furthermore:
i) If the number of arguments does not agree with the number of formal
parameters to the function, the behavior is undefined.
ii) If the function definition was not a definition containing a prototype, then the
type of the actual arguments after promotion must be compatible with the types
of the formal parameters in the definition after they too have had the
promotions applied. Otherwise the behavior is undefined.
iii) If the function definition was a definition containing a prototype, and the types
of the actual arguments after promotion are not compatible with the formal
parameters in the prototype, then the behavior is undefined. The behavior is
also undefined if the prototype included ellipsis(, ...).
2) At the point of calling a function, if a prototype is in scope, the arguments are
converted, as if by assignment, to the types specified in the prototype. Any
arguments which fall under the variable argument list category (specified by the
prototype) still undergo the default argument conversions.

Program 1: /*Function and function calls*/


#include<stdio.h>
#include<conio.h>
/* function declaration */
int max(int numl, int num2);
main()
{
/* local variable definition */
int a = 100; int
b = 200; int ret;
/* calling a function to get maximum value */
ret = max(a, b);
printf("Max value is : %d\n", ret);
getch();

/* function returning the max between two numbers */


int max(int numl, int num2)
/* local variable declaration */
int result;
if(numl>num2)
result = numl;
else
result num2;
return result;
}
Output ____________________

■ C:\Usefs\pravesh\Desktop... a

23

4.1.9. Parameter Passing Mechanism


The mechanism used to pass data to a function is via argument list, where individual
arguments are called actual arguments. These arguments are enclosed in parentheses
after the function name.

The actual arguments must correspond in number, type, and order with formal
arguments specified in the function definition. The actual arguments can be constants,
variables, array names, or expressions.
There are two approaches to passing arguments to a function:
1) Call by Value,
2) Call by Address (Reference).
4.I.9.I. Call by Value
In this type value of actual arguments are passed to the formal arguments and the
operation is done on the formal arguments. Any change made in the formal argument
does not affect the actual arguments because formal arguments are photocopy of actual
arguments.

Hence, when function is called by the call or by value method, it does not affect the
actual contents of the actual arguments. Changes made in the formal arguments are
local to the block of the called function. Once control returns back to the calling
function the changes made vanish.

Important Points Regarding Call by Value Mechanism


1) The actual arguments can be constants, variables, or expressions.
2) When the control is transferred from the calling function to the called function, the
memory for formal arguments and local variables is allocated, values of the actual
arguments are substituted in the corresponding formal arguments, and the
statements in the function body are executed.
3) As soon as the called function finishes its execution, the memory allocated for it is
deallocated, i.e., the values of formal arguments and local variable are destroyed,
and finally the control is transferred back to the calling function.
4) Any change made to the formal arguments will have no effect on actual arguments,
since the function will only be using the local copy of the arguments.
Program 2: */ To send values by call by value*/
#include<stdio.h>
#include<conio.h>
void main()
{
int x, y, change(int, int);
clrscr();
printf("\n Enter values of X and Y:");
scanf("%d%d",&x,&y);
change(x,y);
printf(”\n In main() X=%d Y=%d",x,y);
getch();
}
change(int a,int b)
{
int k;
k=a;
a=b;
b=k;
printf("\n In change() X=%d Y=%d",a,b);
}
Output
c • Turbo C+ * IDE *|

Enter ualues of X and ¥=45 4

In changeO X~4 ¥=45


In nainO X =45 V=4-

Explanation: In the above program we are passing values of the actual argument ‘x’
and ‘y’ to the function change(). The formal argument ‘a’ and ‘b’ of function change()
receives these values(). The values are interchanged, i.e., value of ‘a’ is assigned to ‘b’
and vice versa and printed. When the control returns back to the main(), the changes
made in function change() vanishes. In the main() the values of ‘x’ and ‘y’ are printed
as they are read from the keyboard. In call by value method the formal argument acts as
a photocopy of the actual argument. Hence, changes made in them are temporary.

4.I.9.2. Call by Reference (Address)


Call by reference, the addresses of the actual arguments is used in the function call. In
this way the addresses of the actual arguments are passed to the function.
When control is transferred to the called function, the addresses of the actual arguments
are substituted to corresponding formal arguments and the body of the function is
executed. The formal arguments are declared as pointers to types that match the data
types of the actual arguments. This approach is of practical importance while passing
arrays and structures among function, and also for passing back more than one value to
the calling functions.
If the called function is supposed to return a value, it is returned via return statement.
Additional values can be returned to the calling function via formal arguments which
will be of pointer type.
Important Points Regarding Call by Reference Mechanism
The following rules must be noted about passing arguments using call by reference
mechanism:
1) The actual arguments can only be variables.
2) When the control is transferred from the calling function to the called function, the
memory for formal arguments and local variables is allocated, addresses of the
actual arguments are substituted in the corresponding formal arguments, and the
statements in the function body are executed.
3) As soon as the called function finishes its execution, the memory allocated for it is
deallocated, i.e., the values of formal arguments and local variables are destroyed,
and finally the control is transferred back to the calling function.
4) Any change made to the formal arguments will have immediate effect on actual
arguments, since the function will be working on actual arguments through pointers.
Program 3: /* To send a value by reference to the user-defined function.*/
#include<stdio.h>
#include<conio.h>
void main()
{
int x, y, change(int*, int*);
clrscr();
printf("\n Enter values of X and Y:");
scanf("%d%d", &x, &y);
change(&x, &y);
printf("\n In main() X=%d Y=%d", x, y);
getch();
}
change(int*a, int*b)
{
int *k;
*k=*a;
*a=*b;
*b=*k;
printf("\n In change() X=%d Y=%d", *a,*b);
return;
}
Output
Turbo C- - 11)1

Enter values of X and ¥ :45 56


In change<> X=56 ¥=45 In mainO X=56 ¥=45

Explanation: Here addresses of formal arguments are passed to the function change().
The pointers in the change() receive these addresses() function, i.e., pointer points to
the actual argument. Here the change() function operates on the actual argument
through the pointer. Hence, the changes made in the values are permanent. In this type
of call no return statement is required.
4.1.9.3. Differences between Call by Value and Call by Reference
Table 4.2 shows the some basic difference between call by value and call by
reference.
Table 4.2 ________________
Call by Value Call by Reference

Formal parameter is a new local variable that Formal parameter is an alias for the actual
exists within the scope of the procedure/ parameter.
function/subprogram.
Value of actual parameter is used to initialize Formal parameter refers to the same memory
the formal parameter. cell for the actual parameter.
Changes made to formal parameter DO NOT Each formal parameter is a reference to the
get transmitted back to the caller. actual parameter and modifying the formal
will modify the actual.
C and Java restrict themselves to Call by Value. C++ and Pascal let you declare that a
parameter is a reference.

4.1.10. Types of Functions


A function, depending on whether arguments are present or not and whether a value is
returned or not, may belong one of the following ways:

4.1.10.1. No Arguments and No Return Values


It is the simplest way of writing a user-defined function in C. There is no data
communication between a calling portion of a program and a called function block.
The function is invoked by a calling environment by not feeding any formal arguments
and the function also does not return back anything to the caller.
For example,
main()
{
int x, y;

--------

---------

message(); /* function is invoked */


}
message()
{
/* body of the function */
}
4.1.10.2. Arguments but No Return Values
The second type of writing a user-defined function is passing some formal arguments
to a function but the function does not return back any value to the caller, it is a one
way data communication between a calling portion of the program and the function
block.
For
example,
main()
{
int x, y;
power(x, y); /* function declaration */

---------

---------

}
power(x, y)
int x, y;
{
/* body of the function */
/* no values will be transferred back to the caller */
}
Program: A program to find the square of its number using a function declaration
without using the return statement.
/* passing formal arguments and no return statement */
#include<stdio.h>
#include<conio.h>
main()
{
int i, max;
printf("Enter a value for n ?\n");
scanf("%d", &max);
“ printff'number square \n")
- printf'(“ ____________________ \n");
for(i=0; i<=max-l; ++i)
square(i);
}
square(n)
int n;
{
int temp; temp n*n;
printf("%d\t\t%d\n", n, temp);
}
4.1.10.3. Arguments with Return Values
The third type of writing a user-defined function is passing some formal arguments to a
function from calling the portion of the program and the computed values, if any, is
transferred back to the caller. Data are communicated between calling the portion and a
function block.
For example,
main()
{
int x, y, temp;

char ch;

---------

---------

temp = output(x, y, ch);


}
output(a, b, s) int
a, b;
char s; ^
{
int value;
/* body of the function */
retum(something);
}
Program: A program to find the square of its number using a function declaration using
the return statement.
/* passing formal arguments and return statement */
#inciude<stdio .h>
#include<conio ,h>
main()
{
int i, max, temp;
printf("Enter a value for n?\n");
scanf("%d", &max);
printf("number square \n");
printf(" ______________\n");
for(i=0; i<=max - 1; ++i) {
temp = square(i);
printf("%d\t\t%d\n", i, temp);
}
square(n)
int n;
{
int value;
value = n*n;
retum( value);
}
4.1.10.4. No Arguments but Return a Value
Sometimes one may need to design functions that may not take any arguments but
returns a value to the calling function. A typical example is the getchar function declared
in the header file <stdio.h>. The getchar function has no parameters but it returns an
integer type data that represents a character.

One can design similar functions and use in the programs. For example,
int get_number(void);
main
}
int m = get_number();
printf("%d", m);
}
int get_number(void)
{
int number;
scanf("%d", &number);
retum(number);
}.
4.1.10.5. Functions that Return Multiple Values
If one wants to get more information from a function then he/she can achieve this in C
using the arguments not only to receive information but also to send back information to
the calling function. The arguments that are used to “send-out” information are called
output parameters.

The mechanism of sending back information through arguments is achieved using what
are known as the address operator (&) and indirection operator (*). Let us consider an
example to illustrate this:
void mathoperation(int x, int y, int *s, int *d);
**
main()
{
int x = 20, y = 10, s, d;
mathoperation(x, y, &s, &d);
printf("s=%d\n d=%d\n", s, d);
}
void mathoperation(int a, int b, int *sum, int *diff)
{
*sum = a + b;
*diff = a - b;
}
The actual arguments x and y are input arguments, s and d are output arguments. In the
function call, while we pass the actual values of x and y to the function, we pass the
addresses of locations where the values of s and d are stored in the memory. (That is
why, the operator & is called the address operator.) When the function is called the
following assignments occur:
value of x to a
value of y to b
address of s to sum
address of d to diff
Note: indirection operator * in the declaration of sum and diff in the header indicates
these variables are to store addresses, not actual values of variables. Now, the variables
sum and diff point to the memory locations of s and d respectively. (The operator * is
known as indirection operator because it gives an indirect reference to a variable through
its address.)
In the body of the function, we have two statements:
*sum = a + b;
*diff = a - b;
The first one adds the values a and b and the result is stored in the memory location
pointed to by sum. Remember, this memory location is the same as the memory location
of s. Therefore, the value stored in the location pointed to by sum is the value of s.
Similarly, the value of a - b is stored in the location pointed to by diff, which is the same
as the location d. After the function call is implemented, the value of s is a + b and the
value of d is a - b. Output will be:
s = 30
d= 10
The variables *sum and *diff are known as ‘pointers’ and sum and diff as ‘pointer
variables’. Since they are declared as int, they can point to locations of int type data.

4.2
SCOPE OF VARIABLES

4.2.1. Introduction
In C, the scope of variables can be defined using some storage classes and can define
new type.
Local variables are declared inside a function. These are not known to other functions
outside their own function. In C, local variables are created when the function is called
and destroyed when the functions exit.
Local variables are further divided into auto and static variables.
Global variables declared in main program and are known to all other functions. The
same variable name for global and local variable have the same name then all reference
to that variable name inside the function where the local variables is declared will refer
only to the local variable and will have no effect on the global variable.

4.2.2. Storage Classes


A storage class defines the scope (visibility) and life time of variables and/or functions
within a C Program. These specifiers precede the type that they modify. There are
following storage classes which can be used in a C Program:

1) Auto Storage Class: The auto storage class is the default storage class for all local
variables.
{
/*auto variable declaration*/
int mount;
auto int month;
}
The example above defines two variables with the same storage class, auto can only
be used within functions, i.e., local variables.
2) Register Storage Class: The register storage class is used to define local variables
that should be stored in a register instead of RAM. This means that the variable has a
maximum size equal to the register size (usually one word) and cannot have the
unary operator applied to it (as it does not have a memory location).
{
/*register variable declaration*/

register int miles;


}
The register should only be used for variables that require quick access such as
counters. It should also be noted that defining ‘register’ goes not mean that the
variable will be stored in a register. It means that it might be stored in a register
depending on hardware and implementation restrictions.
3) Static Storage Class: The static storage class instructs the compiler to keep a local
variable in existence during the lifetime of the program instead of creating and
destroying it each time it comes into and goes out of scope. Therefore, making local
variables static allows them to maintain their values between function calls.
The static modifier may also be applied to global variables. When this is done, it
causes that variable’s scope to be restricted to the file in which it is declared.
In C programming, when static is used on a class data member, it causes only one
copy of that member to be shared by all objects of its class.
Program 4: /*Illustrating static storage class.*/
#include<stdio.h>
#include<conic.h>
/* function declaration */
void func(void);
static int count = 5; /* global variable */
main()
{
while(count—)
{
func(); ,
}
return 0;
}
/* function definition */
void func(void)
{
static int i = 5; /* local static variable */
i++;
printf("i is %d and count is %d\n", i, count);
}

4) extern Storage Class: The extern storage class is used to give a reference of a
global variable that is visible to all the program files. When you use ‘extern’ the
variable cannot be initialised as all it does is point the variable name at a storage
location that has been previously defined.
When you have multiple files and you define a global variable or function which
will be used in other files also, then extern will be used in another file to give
reference of defined variable or function. Just for understanding extern is used to
declare a global variable or function in another file.
Program 5: /*lllustrating extern storage class.*/
#include<stdio.h>
#include<conio.h>
int a;
main()
{
extern int b;
printf("%d %d",a,b);
getch();
}
int b=10;

Output
C;\Users\pravesh„J EL! ® J

I
e 10

;4m H
►.1

4.2.3. Features of Storage Class Variables


Table 4.3: Summary of Salient Features of Storage Class VariablesKeyword
—Declaration Statement—Accessibility—Existence—Place
of Storage--Default Value of Variable
auto-- auto data_type variable_name;--Accessible
within the function or block where it is declared.--
Exists from the time of invocation of function or
entry in the block to its return to the calling
function or to the end of the block.—Primary memory—
Garbage
register—register data_type variable_name;--
Accessible within the function or block where it is
declared.--Exists from the time of invocation of
function or entry in the block to its return to the
calling function.--Register of CPU—Garbage
static—static data_type variable_name;--For
Local:Accessible within the function or block where
it is declared. For Global:Accessible within the
program file where it is declared.--For
Local:Preserves value between function calls or
block entries.For Global: Preserves value in the
program file.—Primary memory—Zero
extern-- extern data_type variable_name;--
Accessible within the combination of program modules
that form the full program.-- Exists as long as the
full program is in execution. --Primary memory--Zero
4.3. RECURSION
4.3.1. Introduction
> C supports recursion; i.e., C allows a function to call itself. The basic idea behind
recursion is to decompose a problem into smaller sub-problems which are solved
by recursively calling the function that was called to solve the original problem.
> Recursion is an important programming tool because many algorithms are
naturally recursive.
> Recursion is a process by which a function calls itself repeatedly, until some
specified condition has been satisfied.
> The process is used for repetitive computations in which each action is stated in
terms of a previous result. Many iterative (i.e., repetitive) problems can be
written in this form.
> In order to solve a problem recursively, two conditions must be satisfied:
i) The problem must be written in a recursive form,
ii) The problem statement must include a stopping condition.

For example, suppose we wish to calculate the factorial of a positive integer


quantity. We would normally express this problem as n! = 1 x 2 x 3 x...x n, where n is
the specified positive integer. However, we can also express this problem in another
way by writing n ! = n x ( n - l ) ! This is a recursive statement of the problem, in which
the desired action (the calculation of n!) is expressed in terms of a previous result [the
value of (n — 1)!, which is assumed to be known].

Also, we know that 1! = 1 by definition. This last expression provides a stopping


condition for the recursion.

Program 6: /* Calculate the factorial of an integer quantity using recursion


*/
#include<stdio.h>
#include<conio.h>

long int factorial(int n); /* function prototype */


main()
{ ' int n;
long int factorial(int n);
/* read in the integer quantity */
clrscr();
printf("n =");
scanf("%d", &n);
/* calculate and display the factorial */
printf("nl = %ld\n", factorial(n));
}
long int factorial(int n) /*calculate the factorial */ {
if(n<=l)
retum(l);
else
return (n * factorial (n-1));
}
Output

l Turbo OHK IDE

Explanation: The main portion of the program simply reads the integer quantity n and
then calls the long-integer recursive function factorial. The function factorial calls itself
recursively, with an actual argument, ( n - 1 ) that decreases in magnitude for each
successive call. The recursive calls terminate when the value of the actual argument
becomes equal to 1.

The close correspondence between this function and the original problem definition, in
recursive terms, should be readily apparent. In particular, note that the if-else statement
includes a termination condition that becomes active when the value of n is less than or
equal to 1.

Note: Value of n will never be less than 1 unless an improper initial value is entered
into the computer.

When the program is executed, the function factorial will be accessed repeatedly, once
in main and ( n - 1 ) times within itself, though the person using the program will not be
aware of this. Only the final answer will be displayed, e.g.:

n = 10

n! = 3628800

When a recursive program is executed, the recursive function calls are not executed
immediately. Rather, they are placed on a stack until the condition that terminates the
recursion is encountered. * The function calls are then executed in reverse order, as they
are “popped” off the stack. Thus, when evaluating a factorial recursively, the function
calls will proceed in the following order:
n!=.nx(n-l)! ,
(n - 1)! = (n - 1) x (n - 2)!
(n - 2)! = (n - 2) x (n - 3)!
……………………..
2! = 2x 1!
The actual values will then be returned in the following reverse order:
1! = 1 .
2!=2x1!=2x1=2
3!=3x2!=3x2=6
4!=4x3!=4x6=24

……………….

n! = n x (n - 1)! = •••

This reversal in the order of execution is a characteristic of all functions that are
executed recursively.
If a recursive function contains local variables, a different set of local variables will
be created during each call. The names of the local variables will, of course, always
be the same, as declared within the function. However, the variables will represent a
different set of values each time the function is executed. Each set of values will be
stored on the stack, so that they will be available as the recursive process unwinds,
i.e., as the various function calls are popped off the stack and executed.

4.3.2. Comparison of Iteration and Recursion


Table 4.4: Comparison between Iteration and RecursionIteration
1) It1eration is a process of executing certain set of instructions repeatedly, without
calling the self-function.
2) T2The iterative functions are implemented with the help of for, while, do-while
programming constructs.
3) T3The iterative methods are more efficient because of better execution speed.
4) M4 memory utilisation by iteration is less.
5) It 5 It is simple to implement.
6) T6 The lines of code are more when one uses iteration.
Recursion
1) Recursion is a process of executing certain set of instructions repeatedly by
calling the self-function repeatedly.
2) Instead of making use of for, while, do- while the repeatation in code execution is
obtained by calling the same function again and again over some condition.
3) The recursive methods are less efficient.
4) Memory utilisation is more in recursive functions.
5) Recursive methods are complex to implement.
6) Recursive methods bring compactness in the program.

4.4. 'POINTERS
4.4.1. Introduction
> Pointers are widely used in programming; they are used to refer to memory
location of another variable without using variable identifier itself. They are
mainly used in linked lists and call by reference functions.
> With pointer we can perform lot many operations by using memory addresses. It is
possible to access and display the memory location of a variable using ‘&’
operator.
> A pointer variable holdfe the memory address of any type of variable. The pointer
variable and normal variable should be of the same type. The pointer is denoted by
symbol. „

4.4.2. Uses of Pointers


1) Pointers are more efficient in handling arrays and data tables.
2) Pointers can be used to return multiple values from a function via function
arguments.
3) Pointers permit references to functions and thereby facilitating passing of functions
as arguments to other functions.
4) The use of pointer arrays to character strings results in saving of data storage space
in memory.
5) Pointers allow C to support dynamic memory management.
6) Pointers provide an efficient tool for manipulating dynamic data structures such as
structures, linked lists, queues, stacks and trees.
7) Pointers reduce length and complexity of programs.
8) They increase the execution speed & thus reduce the program execution time.

4.4.3. Understanding Memory Addresses


^ In computer memory, each location where a piece of data can be stored is identified
by a memory address. A memory address is similar to a street address - just as 345
and 347 identify different houses on a street, different memory locations are
labeled with address numbers. Memory address numbers are usually large numbers
with many digits because the memory of a computer likely has billions of locations
where data can be stored.
> When you declare a variable with a statement such as int myAge; the computer
chooses an available memory location in which to store the integer, and then associates
the name myAge with the memory address of that location.
> All modem programming languages allow you to use easy- to-remember variable
identifiers - like myAge - so that you do
not have to remember actual memory
addresses. An address is a reference to a
variable (or object), i.e., just as 345 refer to
a specific house, a memory address refers to
a specific object in memory.
> A variable’s memory address is a
fixed location, it is a constant. In
Other words, a variable’s address from low
to high Low Addresses
is not changeable; when you Figure 4.1: Memory
declare a variable, it is stored at a specific memory address that cannot be altered.
Although you cannot choose a variable’s actual memory address, for assigning the
memory to a variable we use the address operator (&), also called the reference
operator. Address operator is a unary operator that returns the address of the
variable that follows it.
Here is a simple figure 4.1 which shows showing the arrangement of computer
memory perplexed one. Memory is essentially an array of byte addressable elements
in which binary values can be stored. Memory addresses start at zero and goes upto
however much memory you have in your computer.
> Hardware architecture of the computer system dictates how physical memory is
arranged and accessed, but here we will assume that the word size is 32 bits.
Looking at figure 4.1, memory starting at address 0 contains the four bytes with
addresses 0, 1, 2, and 3 for a total of 32 bits. The 32-bit memory words are aligned
on addresses divisible by 4, which is why the addresses 0, 4, 8, 12, etc., are going-
up the left side of memory in the diagram.

Figure 4.2 shows another way of representing memory that reinforces the idea that
it is a contiguous array of elements:
00000000 00000000 00000000 00000001 00000000 00000000 000000000 00000010 00000000 00000000
0 1 2 3 4 5 6 7 8
9 A

Figure 4.2: Another Way to Represent Memory

Figure 4.2 also shows the memory initialized with two integer values. The integer
object beginning at address 0 has a value of 1. The second integer object begins at
address 4 and contains the value 2.

4.4.4. Address of Operator/Address Operator (&)


The unary address-of operator (&) takes the address of its operand. The operand of the
address-of operator can be either a function designator or an 1-value that designates an
object that is not a bit field and is not declared with the register storage-class specifier.

The address-of operator can only be applied to variables with fundamental, structure,
class, or union types that are declared at the file-scope level, or to subscripted array
references. In these expressions, a constant expression that does not include the
address-of operator can be added to or subtracted from the address-of expression.
When applied to functions, the result of the expression is a pointer type (an rvalue)
derived from the type of the operand. For example, if the operand is of type char, the
result of the expression is of type pointer to char. The address-of operator, applied to
const or volatile objects, evaluates to const type* or volatile type*, where type is the
type of the original object.

For example, suppose v is a variable that represents some particular data item. The
compiler will automatically assign memory cells for this data item. The data item can
then be accessed if we know the location (i.e., the address) of the first memory cell.

Address of v’s memory location can be determined by the expression &v, where & is a
unary operator, called the address operator, that evaluates the address of its operand.

Now let us assign the address of v to another variable, pv. Thus,

pv = &v

This new variable is called a pointer to v, since it “points” to the location where v is
stored in memory, pv represents v’s address, not its value. Thus, pv is referred to as a
pointer variable. The relationship between pv and v is illustrated in
figure4.3

Value of v
Address of v

pv

Figure 4.3: Relationship between pv and v (where pv = &v and v = *pv)

The data item represented by v (i.e., the data item stored in v’s memory cells) can be
accessed by the expression *pv, where * is a unary operator, called the indirection
operator, that operates only on a pointer variable. Therefore, *pv and v both represent
the same data item (i.e., the contents of the same memory cells). Furthermore, if we
write pv = &v and u = *pv, then u and v will both represent the same value, i.e., the
value of v will indirectly be assigned to u. (It is assumed that u and v are of the same
data type).

4.4.5. Definition
A pointer is a variable that points to another variable. This means that it holds the
memory address of another variable. So we can say that, the pointer does not hold a
value in the traditional sense; instead, it holds the address of another variable. It points
to that other variable by holding its address.

Because a pointer holds an address rather than a value, it has two parts. The pointer
itself holds the address. That addresses points to a value. There is the pointer and the
value pointed to.
For example, consider the following program, ‘
#include<stdio.h>
void main() '
{
inti, j;
int *p;/* a pointer to an integer */
p = &i;
*p = 5;
j = i;
printf(“%d %d %d\n”, i, j, *p);
}
Explanation: The line int *p declares a pointer. It asks the compiler to declare a variable p that is a
pointer to an integer. The * indicates that a pointer is being declared rather than a normal variable.
Programmer can create a pointer to anything: a float, a structure, a char, and so on.
The line p = &i;. expression &i means “the memory address of the variable i”. Thus, the expression p
= &i; means “Assign to p the address of i . Once programmer executes this statement, p points to i.
Before he does so, p contains a random, unknown address, and its use will likely cause a
segmentation fault.

After the line p = &i; the memory situation looks something like this:

*
_______________________ ______________________________________
Note: p is represented by a circle to indicate that it is a pointer, while i is represented by a square to
indicate that it is a normal variable.

Once p points to i, the memory location i has two names. It is still known as 1, but now it is known as
*p as well. This is how C talks about the two parts of a pointer variable: p is the location holding the
address, while *p is the location pointed to by that address. Therefore *p = 5 means that the location
pointed to by p should be set to 5. Because this location is also i, i also take on the value 5.
Consequently, j = i; sets j to 5, and the printf statement produces 5 5 5.

4.4.6. Declaration of Pointer


C programming language supports pointers to different data types - int, float, double, char, etc. Every
pointer can point to either a single value or to multiple values. Whether a pointer is to point to a
single value or to multiple values (in the case of a pointer to an array) is decided by its specific use
with the associated constructs of the program. In C a pointer variable is declared by using the pointer
(*) operator.
Syntax: int *pi; /* pi is an integer pointer/pointer to an integer */
float *pf; /* pf is a float pointer */
char *pc; /* pc is a character pointer */
Here, the pointer variables pi, pf and pc contain a pointer to the corresponding data item.
Consider the declaration of int *pi; Here, pi is a pointer variable which is capable of
holding the address of the memory location containing an integer. When the compiler
comes across this statement, it allocates a location that can store the address of an integer
location. Hence, a pointer is an address variable that holds the physical address of the
data item.

Figure 4.4 gives a pictorial view of pointers and memory, where Address: x is the
address of an integer location x:

pi Address: x

Figure 4.4: Pointers and Memory

For example, Consider the following program segment where a is an integer variable,
pi is a pointer to an integer variable and &a gives the address of the integer variable
a:

int a = 10;

int *p;

p=&a;

After compilation, we have the values in the variables as shown in figure 4.5:

pi addr

10

Figure 4.5: Memory Status after Compilation


After execution of the first statement, i.e., p = &a; the values of the variables will be
as shown in figure 4.6.
Figure 4.6: Memory Status after Execution of Statement
Pointers allow indirect access to data. One can read a value into a variable in two
different ways.
1) Direct Access,
2) Indirect Access.
The following statements illustrate direct access and indirect access to the data:
scanf(“%d”, &a); /* Direct access */ __
scanf(“%d”, p); /* Assume that the statement p = &a has been executed, indirect
access */ _________ __________________

p X P X P y
q y q y q y
X 10 X 20 X 10
>
y 20 y 20 y 20

(a) (b) (c)


Figure 4.7: (a) Memory Status before Assignment; (b) Memory Status after
Assignment of *p = *q from (a); (c) Memory Status after Assignment of p = q
from

Basically the pointers have two types of assignment operations, namely *p = *q and
p = q, and are depicted in figure 4.7. After assignment of *p = *q, the value pointed
to by the pointer q is copied to the location pointed to by the pointer p, and both of
them have the value 20 as shown in figure 4.7. Similarly, after assignment of p = q,
the address stored in the pointer q is copied into the pointer p. Both the pointers point
to the same memory location and hence the value of *p and *q is the same, i.e., 20.

4.4.7. Initialization of Pointer


Pointer variables can be initialized in their definitions, just like many other variables
in C.
For example, the following two statements allocate storage for the two cells iresult
and piresult:
1) int iresult;
2) int *piresult = &iresult;

The variable iresult is an ordinary integer variable, and piresult is a pointer to an


integer.
Additionally, the code initializes the pointer variable piresult to the address of iresult.
We are not initializing *piresult (which would have to be an integer value) but
piresult (which must be an address to an integer).

Second statement in the preceding listing can be translated into the following two
equivalent statements:
int *piresult;
piresult = &iresult;
4.4.8.Indirection Operator
An indirection or pointer operator is represented by a combination of asterisk (*)
with a variable.

Syntax: *
int *ptr; // ptr is a pointer variable which holds the address of an integer data
type.
float *fpointer;
double *dpoint;
char *cpointl;

Indirection/Dereferencing is an operation performed to access and manipulates data


contained in the memory location pointed to by a pointer.
Or
The process of following a pointer to the location to which it points is called
indirection or dereferencing the pointer. The operator * is used to dereference
pointers.

A pointer variable is dereferenced when the unary operator *, in this case called the
indirection operator, is used as a prefix to the pointer variable or pointer expression.

If the operand points to a function, the result is a function designator. If it points to a


storage location, the result is an 1-value designating the storage location. If the
pointer value is invalid, the result is undefined.

The following list includes some of the most common conditions that invalidate a
pointer value.
1) The pointer is a null pointer.
2) The pointer specifies the address of a local item that is not visible at the time of
the reference.
3) The pointer specifies an address that is inappropriately aligned for the type of the
object pointed to.
4) The pointer specifies an address not used by the executing program.

Any operation performed on the dereferenced pointer directly affects the value of the
variable it points to. For example, consider the following program

Program 7: illustrates dereferencing of pointer (derefer.c).


#include<stdio.h>
#include<conio.h>
void main()
{
int *iptr, varl, var2;
iptr = &varl; /* initialize pointer iptr */
*iptr = 25; /* dereference iptr, varl = 25, */
*iptr += 10; /* varl = varl + 10; */
/* next statement prints varl, it should be 35 */
clrscr();
printf("Variable varl contains: %i\n", varl);
var2 = *iptr; /* same as var2 = varl; */
/* next statement prints var2, it also contains 35 */
printf("Variable var2 contains: %i\n", var2);
iptr = &var2; /* iptr now points to var2 */
*iptr += 20; /* increase contents of var2 by 20, */
/* next statement prints var2, it now contains 55 */
printf("Variable var2 now contains: %i\n", var2);
}

Explanation
1) The asterisk (*) used as an indirection operator has a different meaning from the
asterisk used to declare pointer variables:
int *ptr; /* This is a pointer declaration */
*ptr = 100; /* The LHS does pointer indirection */
2) Indirection allows the contents of a variable to be accessed and manipulated without
using the name of the variable.
3) All variables that can be accessed directly (by their names) can also be accessed
indirectly by means of pointers. The power of pointers becomes evident in situations
where indirect access is the only way to access variables in memory.

4.4.8. Pointer Arithmetic


The C language allows programmer to add and subtract integers to and from pointers.
For example, if p is a pointer, the expression p+3 is perfectly legal, meaning three
objects after the object that p points to. Because p holds an address, performing
arithmetic on p generates a new address value. However, rather than simply adding 3 to
p, the compiler multiplies the 3 by the size of the object that p points to. This is called
scaling.
In pointer arithmetic, all pointers increase or decrease by the length of the data type
pointed to by them. This length is known as the scale factor. The scale factors for
various data types on an IBM PC and its compatibles are:
Data Type Length
char 1 byte
int 2 bytes
float 4 bytes
long int 4 bytes
double 8 bytes

For example, the figure 4.8 illustrates the concept of pointer arithmetic:
char *cptr;
float *fptr;

int *iptr;

2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
cpt cptr+1 cptr+2 cptr+3 cptr+4 cptr+5 cptr+6 cptr+7 cptr+8 cptr+9 cptr+10 cptr+11

■l _______ l l ________ ll ________ ll ________ ll ________ il


_________ I
iptr iptr+1 iptr+2 iptr+3 iptr+4 iptr+5
I _________________ I I _________________ I I ---------------------------- 1
fptr fptr+1 fptr+2
Figure 4.8: (Showing Pointer Arithmetic Relative to its Base Type)

An important point about the pointer variable is that it holds the address of the very first
byte of the memory location pointed to by it, known as the base address.

For example, suppose that the address value held by p is 1000. If p is declared as ' a
pointer to a 4-byte long int, the 3 in p+3 is multiplied by 4. The value of p+3, therefore,
is 1012. '

On the other hand, if p is declared as a pointer to a char, p+3 would equal 1003. In this
way, the expression p+3 always means 3 objects after p, regardless of the type of object
that points to.

The following arithmetic operations on pointers are not permitted:


i) Addition of two pointer variables.
ii) Multiplication of a pointer variable by a number.
iii) Division of a pointer variable by a number.

4.4.9.I. Incrementing a Pointer


Generally programmers use a pointer in the program instead of an array because the
variable pointer can be incremented, unlike the array name which cannot be incremented
because it is a constant pointer. Following program increments the variable pointer to
access each succeeding element of the array:

Program 8: To illustrate the increment of a pointer.


#include <stdio.h>
#include<conio.h>
const int MAX = 3;
main ()
{

int var[] = {10, 100, 200};

int i, *ptr;

/* let us have array address in pointer */


ptr = var;
for (i = 0; i < MAX; i++)
{
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr);

/* move to the next location */ ptr++;


}
getch();
}
Output
81C:\Users\pravesh\Desktop\ToV.?[

4A.9.2. Decrementing a Pointer


The same concerns as apply in increment of a pointer is apply to decrementing a
pointer, which decreases its value by the number of bytes of its data type as shown
below in the program:

Program 9: To illustrate the concept of decrementing a pointer.


#include <stdio.h> '
#include<conio.h
> const int MAX
= 3;

main ()
{
int var[] = {10, 100, 200};
int i, *ptr;

/* let us have array address in pointer */


ptr = &var[MAX-l];
for (i =• MAX; i > 0; i—)
{
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr);
/* move to the previous location */
ptr-;
}
getch();
}-
4.4.9.3. Pointer Comparisons
Pointers may be compared by using relational operators, such as = =, <, and >. If pi
and p2 point to variables that are related to each other, such as elements of the same
array, then pi and p2 can be meaningfully compared. Consider the following program
which illustrates the pointer comparison.

Program 10: To illustrate the comparing the pointer.


#include<stdio.h>
#include<conio.h>

int main()
{
int data[100];
int* pi;
int *p2;
int i; ,
clrscr();
for(i=0;i<100;i++)
{
data[i]= i;
}
p1 = &data[l];

p2 = &data[2];

if(pl>p2)
{
printf(”\n\n pi is greater than p2");
}
else
{
printf("\n\n p2 is greater than pi");
}
Output

4-5. MEMORY ALLOCATION


Any program or data must be loaded into memory before it can be executed or
processed. Therefore, for every program to be executed or data to be processed,
some memory must be allocated for them.
One of the important aspects of pointer is memory allocation. There are two types
memory allocation possible in C.

4.5.1. Static Memory Allocation


In the static allocation, the required amount of memory is allocated to the program
element (identifiers names which include variable name, function name, program
name etc.) at the start of program.
The main drawback of static allocation if there is less number of elements than then
the rest amount of memory is wasted. The concept Dynamic or run time memory
allocation help to overcome this problem.

4.5.2. Dynamic Memory Allocation


It makes efficient use of memory, by allocating the require amount of memory
whenever needed, unlike static allocation where the amount to be declared statically.
Dynamically allocated variables are simply variables that do not exist when the
program is loaded, but are created dynamically as they are needed. It is possible,
using these techniques, to create as many variables as needed, use them, and de-
allocate their space for use by other variables.

4.5.2.I. Definition
Process of allocating memory at run time is known as dynamic memory allocation.
Dynamic allocation is a technique in which program can acquire storage space in the
main memory. In this method, the space for the program is allocated from the ' free
space during execution of the program. The free region of the memory is called the
heap.
The heap changes depend upon what memory model is being used. The amount of
memory requirement is decided by how the program is designed.
Stack

Free memory for allocation


High

Global Variables

Low
Program

Figure 4.9: C Program’s use of Memory Table 4.5: Dynamic Memory Allocation Functions

malloc()---- Allocates request size of bytes and returns a pointer to the first byte of the

allocated space-- ptr = (cast-type *) malloc(byte-size);

calloc()---- Allocates space for an array of elements, initializes then to zero and then returns a

pointer to the memory-- ptr = (cast-type *) calloc(n, elem-size);

free()---- Frees previously allocated space-- free (ptr);

realloc()---- Modifies the size of previously allocated space-- ptr = realloc(ptr, newsize);

ptr is a pointer to a memory block which has already been created by malloc() or
calloc().

4.5.2.2. malloc() Function


malloc() requires one argument - the number of bytes you want to allocate
dynamically. It returns the address of memory chunks that is allotted.

If the memory allocation was successful, malloc() will return a void pointer - you can
assign this to a pointer variable, which will store the address of the allocated memory.

If memory allocation failes (e.g if the system is out of memory), malloc() will return a
NULL pointer.
Passing the pointer into free will release the allocated memory - it is good practice to
free memory when its usage is finished.
Program ll:/*illustrating malloc function*/
#include<stdio.h>
#include<conio.h>
main()
{
int *ptr_one;
ptr_one = (int *)malloc(sizeof(int));
if (ptr_one == 0)

printf("ERROR: Out of memoryNn");


return 1;
}
*ptr_one = 25;

printf("%d\n", *ptr_one);

free(ptr_one);
getch();
}
Output _________
i * C:\Users\praves.,
23

Explanation .
The malloc statement will ask for an amount of memory with the size of an integer
(32 bits or 4 bytes). If there is not enough memory available, the malloc function will
return a NULL. If the request is granted a block of memory is allocated (reserved).
The address of the reserved block will be placed into the pointer variable.

The if statement then checks for the return value of NULL. If the return value equals
NULL, then a message will be printed and the programs stops. (If the return value of
the program equals one, than that’s an indication that there was a
problem.)
The number 25 is placed in the allocated memory. Then the value in the allocated
memory will be printed. Before the program ends the reserved memory is
released.

4.5.2.3. calloc() Function


callocO is similar to malloc(), but the main difference is that the values stored in the
allocated memory space is zero by default.
calloc() Arguments: It requires two arguments. The first is the number of variables
that the programmer would like to allocate memory for. The second is the size of
each variable.

calloc() returns a void pointer if the memory allocation was successful, else it’ll
return a NULL pointer. We can free memories by using the free() function.

Program 12: illustrating calloc() function.


#include <stdio.h>
#include <stdlib.h>
tnain()
{
int i, n;
int *a;

printf("Number of elements to be entered:");


scanf("%d",&n); ’
a = (int*)calloc(n, sizeof(int));
printf(“-"Enter %d mbers:\n",n);

for( i=0 ; i < n ; i++ )


{
scanf("%d",&a[i]);

}
1
printf("The numbers entered are: ");

for( i=0 ; i < n ; i++ )


{
printf("%d ",a[i]);
}
getch();
}

Output

* C:\Users\pravesh\Oeddop\t\check5sep^xe I, 1=3 j _____________ £3 j

4.5.2.4. realloc() Function


•The realloc() function change the size of previously dynamically allocated memory
without changing the contents of the memory.
If the done allocation of memory is not sufficient for the programmer’s use then
there are two ways to again dynamically extend memory.
1) First is to copy everything into a larger array, which is inefficient, and
2) Second allocate more bytes using realloc, without losing data.
realioc() Arguments: realloc 4akes two arguments. The first is the pointer
referencing the memory. The second is the total number of bytes that are to be
reallocated. Passing zero as the second argument is the equivalent of calling free.
Once again, realloc returns a void pointer if successful, else a NULL pointer is
returned.

Free() Function: When your program comes out, operating system automatically
release all the memory allocated by your program but as a good practice when you
are not in need of memory anymore then you should release that memory by calling
the function free().
Program 13: To illustrate the use of realloc function.
#include <stdio.h>
#include <stdlib.h>
main()
{
char *str;
/* Initial memory allocation */
str = (char *) malloc(15);
strcpy(str, "TPPL"); ^
printf("String = %s, ’Address = %u\n", str, str); .
/* Reallocating memory */
str = (char *) realloc(str, 25);
strcat(str, ".com");
printf("String = %s, Address = %u\n", str, str);
free(str);
getch();
}.
Output
a C:\Users\pravesh\Desktop\t\cheek5sep.exe
4.5.2.5. Comparison among Memory Allocation Function Table 4.6:
Comparison of malloc(), caIloc() and realloc()

Basis--- malloc()----calloc()----reaIIoc()

No. of Arguments-- 1-- 2-- 2

No. of Bytes---- Total no. of bytes required---- No. of elements


and size of elements---- No. of bytes required for expansion

Type of Data---- Type of data unknown--- Type of data known---


Dynamic allocation while working in the code.
Deallocation---- Free is used explicitly to free the memory-----
Free is used explicitly to free the memory----- realloc itself can
be used for freeing the memory

4-6, FUNCTIONS AND POINTERS


One of the most useful applications of pointers is in functions. We know that C
function can pass parameters in two ways one is pass by value and other one is pass
by reference.

In the pass by value is that only direct way to send values from calling function to
called function and it returns processed value through only return statement. And in
pass by reference by passing an address from calling function to called function and
it returns changed data is called function to the calling function program.
This concept is also called as pass by reference (address). When we pass by address,
we are actually passing a pointer to a variable.

4.6.1. Pointer as Formal Parameters


Consider the program below to specify the concept of pass by value. Here, we call
the swap function, passing two variables whose contents are to be exchanged. In their
process, the contents are exchanged in the called function but it is not reflected in the
main program i.e., nothing is changed in the calling function program.

Program: illustrating as formal parameters.


#include<stdio.h>
void main()
{
int a = 10;
int b = 20;
swap(a, b);
printf(“%d %d\n”, a, b);
}
void swap (int x, int y)
{
int temp;
temp= x;
x = y; .
return y
= temp;
}
Instead of using pass by value to swap two elements, we can use a pass pointers to the
value i.e. pass by reference. Once we are making use of pointer to variable it does not
make any difference in terms of local variable within main () function or if it is global
variables but we can exchange these two values.
In the program below shows the exchange two values using pointers^ To define a
pointer we use the address operator (and) in the calling function is shown below. Now,
we are passing address of two variable i.e., a and b refer than their values.
swap (&a, &b);
The usages of pass by address, in the called function formal parameters are defined as
pointer to a variable. It establishes the link and allows us to indirectly reference the
variable in the calling program using pointers.
void swap(int*, int*);
To assign-a value of a, we need to use dereference the pointer in swap function. This
operation allows to access data in the calling program using the pass by address. It is
very important, to know that. C still uses only pass y a v ue. n this situation, the value
is the reference (address) of the variable we require to change.

Program 13
#include<stdio.h>
void swap (int*, int*);
int main()
{
int a, b;
a = 10;
b = 20;
swap(&a, &b);
printf(“%d %d\n”, a, b);
}
void swap (int *x, int *y)
{
int temp;
temp = *x; temp 10
*x = *y; xy Program. Swap Two Variables Using pointers
= temp;
swap() function is called using the. address operator for the variables that is required
to exchange two values.

Note: The swap() function uses two formal parameters i.e., x and y along with temp local variable.
Using the dereferencing the parameters, we perform the swap using the variables in main and lowcal
variable temp in swap. The complete working program is shown in the program above.

4.6.2. Functions Returning Pointers


A pointer is also a data type C,we can also force a function to return a pointer to the
calling function consider the program below contains a function to
determine the larger of two numbers. Here, we need a pointer to the large of two
vanables a and b. Since we are using two pointers to a function, whfch uses a
condition expression to determine which value is larger.

Once after knowing the larger value, we can return address of its location as pointer.
The return address is then assigned in the calling function pointer p, so that after
calling the function it points to either a or b based on their values. The corresponding
C program and its equivalent diagram of the variable and pointer are shown in figure
4.10.

Program: illustrating functions returning pointer.


#include<stdio.h>
int *larger (int *x, int *y);
void main()
{
int a,b;
int *p;
printf(“enter the value of a nad b/n”);
scanf(“%d %d”, &a, &b);
p = larger(&a, &b);
printf(“largest = %d\n”, p);

int *larger(int *x, int *y)


{
return (*x>*y? *x : *y);
.X J
} Figure 4.10: Function
Returning Pointers
Note: The address must be the address or the variable in the calling function It is an error to return a
pointer to a local variable in the called function, because when the function terminates, its memory
may be used by other parts of the program. Although such a simple program may not notice such
type error because space was not reused, but a large programs may get wrong answer or fail when
the memory being referenced by the pointer was changed.
4.7. PROGRAMS
Program 14: To caluclate square of a value using function.
#include<stdio .h>
#include<conio.h>

// function prototype, also called function declaration float


square (float x );
main()
{
float m, n ;
printf ("\nEnter some number for finding square \n");
scanf ( " % F , & m ) ;
// function call
n = square ( m); ^
printf ("\nSquare of the given number %f is %f",m,n);
getch();
}
// function definition float square (float x)
{
float p ;
p=x*x
;
return
(p) ;
}

Example 15: Program to add 1 + 2 + . . . + 100 using a pointer to a function method.


#include<stdio.h>
#include<conio.h>
main()
{
int n, a, sum(int n);
int(*ptr)(int n);
printf("Enter the value of n\n");
scanf("%d", &n);
ptr = &sum;
a = (*ptr)(n);
printf("Sum = %d\n", a);
getch();
}
int sum(int n)
{
int i, j;
j = 0;
for(i=l; i<=n; i++)
{
j += i;
}
return(j);
}

Program 16: Prime Numbers Between two Intervals by Making User-defined


Function.
#include<stdio.h>
#include<conio.h>
int check_prime(int num);
main(){
int nl,n2,i,flag;
printf("Enter two numbers(intervals): ");
scanf("%d %d",&nl, &n2);
printf("Prime numbers between %d and %d are: ", nl, n2);
for(i=n 1+1 ;i<n2;++i) ’’’
{
flag=check_prime(i);
if(flag==0) 7
printf("%d ",i);
}
getch();
}
int check_prime(int num)
{
int j,flag=0;
for(j=2;j<=num/2;++j){
if(num%j==0){
flag=l;
break;
}
}
return flag;
}
Output:
■ C:\Users\prawesh\Desktop\To\VTU je*e

Program 17: To reverse a sentence using recursion.


#include <stdio.h>
#include<conio.h>
void Reverse();
main()
{
printf("Enter a sentence: ");
Reverse();
getch();
}
void Reverse()
{
char c;
scanf("%c",&c);
if( c != V)
{
Reverse();
printf("%c",c);
}
}
Output ___
4.8. EXERCISE
1) What do you understand by pointers? Give the syntax of declaration of a pointer.
2) Find the output of the following program: '
main()
{
int x=5, *p;
p=&x;
printf("%d'\ ++*P);
}
3) What will be the output of following block?
4) main()
{
int arr[5]=[3, 4, 6, 2, 1];
int *p=arr; «
int *q=arr+2;
int *r=&arr[l];
printf("\n%d %d%d", arr[2], *(arr+2),*r);
printf("\n%d%d%d", *p, *(q+l),*(r+l));
return 0;
}
5) How do you use a pointer to a function?
6) Discuss the various arithmetic operations performed on a pointer.
7) Explain the use of (*) indirection operator?
8) Explain the effect of ++ and - operator with pointer of all data types?
9) Why addition of two pointers is impossible?
10) Explain the relation between an array and a pointer?
11) Distinguish between the address stored in the pointer and the value at that address?
12) What is the base address? How is it accessed differentially for one-dimensional and twodimensional
arrays?
13) Explain the comparison of two pointers?
14) Explain the feature of pointers?
15) How strings are stored using pointer variables? Is it essential to declare length?
16) Write a program to sort 10 strings with the help of pointers.

Das könnte Ihnen auch gefallen