PPS Unit-4
PPS Unit-4
A function is a group of statements that together perform a task. Every C program has at least one function,
which is main(), and all the most trivial programs can define additional functions.
You can divide up your code into separate functions. How you divide up your code among different
functions is up to you, but logically the division is such that each function performs a specific task.
A function declaration tells the compiler about a function's name, return type, and parameters. A function
definition provides the actual body of the function.
The C standard library provides numerous built-in functions that your program can call. For example,
strcat() to concatenate two strings, memcpy() to copy one memory location to another location, and many
more functions.
A function definition in C programming consists of a function header and a function body. Here are all the
parts of a function −
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 return_type is the keyword void.
Function Name − This is the actual name of the function. The function name and the parameter
list together constitute the function signature.
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; that is, a
function may contain no parameters.
Function Body − The function body contains a collection of statements that define what the
function does.
Example
Given below is the source code for a function called max(). This function takes two parameters num1
and num2 and returns the maximum value between the two −
int result;
result = num1;
else
result = num2;
return result;
Function Declarations
A function declaration tells the compiler about a function name and how to call the function. The actual
body of the function can be defined separately.
A function prototype is simply the declaration of a function that specifies function's name, parameters and
return type. It doesn't contain function body.
A function prototype gives information to the compiler that the function may later be used in the program.
In the above example, int addNumbers(int a, int b); is the function prototype which
provides following information to the compiler:
The function prototype is not needed if the user-defined function is defined before the main() function.
Category of functions:
A function depending an whether the arguments are present or not and whether a value is
returned or not, may belong to one of following categories
In this category, the function has no arguments. It does not receive any data from the calling
function. Similarly, it doesn‟t return any value. The calling function doesn‟t receive any data
from the called function. So, there is no communication between calling and called functions.
In this category, function has some arguments . it receives data from the calling function, but it
doesn‟t return a value to the calling function. The calling function doesn‟t receive any data
from the called function. So, it is one way data communication between called and calling
functions.
Eg: Printing n Natural numbers
#include<stdio.h>
#include<conio.h>
void nat( int);
void main()
{
int n;
printf("\n Enter n value:");
scanf("%d",&n);
nat(n);
}
void nat(int n)
{
int i;
for(i=1;i<=n;i++)
printf("%d\t",i);
}
Note:
In the main() function, n value is passed to the nat() function. The n value is now stored in the
formal argument n, declared in the function definition and subsequently, the natural numbers
upto n are obtained.
In this category, functions has some arguments and it receives data from the calling function.
Simillarly, it returns a value to the calling function. The calling function receives data from the
called function. So, it is two-way data communication between calling and called functions.
#include<stdio.h>
#include<conio.h>
int fact(int);
void main()
{
int n;
printf("\n Enter n:");
scanf("%d",&n);
printf("\n Factorial of the number : %d", fact(n));
}
int fact(int n)
{
int i,f;
for(i=1,f=1;i<=n;i++)
f=f*i;
return(f);
}
In this category, the functions has no arguments and it doesn‟t receive any data from the calling
function, but it returns a value to the calling function. The calling function receives data from
the called function. So, it is one way data communication between calling and called functions.
Eg. Sum of Numbers
#include<stdio.h>
#include<conio.h>
int sum();
void main()
{
int s;
printf("\n Enter number of elements to be added :");
s=sum();
printf("\n Sum of the elements :%d",s);
int sum()
{
int a[20], i, s=0,n;
scanf("%d",&n);
printf("\n Enter the elements:");
for(i=0;i< n; i++)
scanf("%d",& a[i]);
for(i=0;i< n; i++)
s=s+a[i];
return s;
}
Downward Communication
Upward Communication
Bi-directional Communication
Downward Communication
In this type of communication, the data is transferred from calling function to called function but not
from called function to calling function. The function with parameters and without return value are
considered under Downward communication.
Example
#include <stdio.h>
#include<conio.h>
void main(){
int num1, num2 ;
void addition(int, int) ; // function declaration
clrscr() ;
num1 = 10 ;
num2 = 20 ;
getch() ;
}
void addition(int a, int b) // called function
{
Output
SUM=30
Upward Communication
In this type of communication, the data is transferred from called function to calling function but not
from calling function to called function. The function without parameters and with return value are
considered under Upward communication.
Example
#include <stdio.h>
#include<conio.h>
void main(){
int result ;
int addition() ; // function declaration
clrscr() ;
Output
SUM=30
Bi-Directional Communication
In this type of communication, the data is transferred from called function to calling function and also
from calling function to called function. The function with parameters and with return value are
considered under Bi-Directional communication.
Example
#include <stdio.h>
#include<conio.h>
void main(){
int num1, num2, result ;
int addition(int, int) ; // function declaration
clrscr() ;
num1 = 10 ;
num2 = 20 ;
Function Calls
This calls the actual function
Syntax:
function_name (arguments list);
There are two ways that a C function can be called from a program. They are,
1. Call by value
2. Call by reference
Call by Value
In call by value method, the value of the variable is passed to the function as parameter.
The value of the actual parameter can not be modified by formal parameter.
Different Memory is allocated for both actual and formal parameters. Because, value of actual
parameter is copied to formal parameter.
Note:
Call by Reference:
In call by reference method, the address of the variable is passed to the function as parameter.
Same memory is used for both actual and formal parameters since only address is used byboth
parameters.
In C Programming we have different ways of parameter passing schemes such as Call by Value and Call
by Reference.
Function is good programming style in which we can write reusable code that can be called whenever
require.
Whenever we call a function then sequence of executable statements gets executed. We can pass some of
the information to the function for processing called argument.
Two Ways of Passing Argument to Function in C Language :
A. Call by Reference
B. Call by Value
Let us discuss different ways one by one –
A. Call by Value :
#include<stdio.h>
void interchange(int number1,int number2)
{
int temp;
temp = number1;
number1 = number2;
number2 = temp;
}
int main() {
int num1=50,num2=70;
interchange(num1,num2);
printf("\nNumber 1 : %d",num1);
printf("\nNumber 2 : %d",num2);
return(0);
}
Output :
Number 1 : 50
Number 2 : 70
In the above example num1 and num2 are the original values and xerox copy of these values is passed to
the function and these values are copied into number1,number2 variable of sum function respectively.
As their scope is limited to only function so they cannot alter the values inside main function.
B. Call by Reference/Pointer/Address :
#include<stdio.h>
void interchange(int *num1,int *num2)
{
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
int main() {
int num1=50,num2=70;
interchange(&num1,&num2);
printf("\nNumber 1 : %d",num1);
printf("\nNumber 2 : %d",num2);
return(0);
}
Output :
Number 1 : 70
Number 2 : 50
Call by Address
While passing parameter using call by address scheme , we are passing the actual address of the variable
to the called function.
Any updates made inside the called function will modify the original copy since we are directly
modifying the content of the exact memory location.
Passing Array to a Function:
There are two possible ways to do so, one by using call by value and other by using call by
reference.
Or, we can have a pointer in the parameter list, to hold the base address of our
We don't return an array from functions, rather we return a pointer holding the base address of the
array to be returned.
In this type of function call, the actual parameter is copied to the formal parameters.
Example 1:
#include<stdio.h>
void giveMeArray(int a);
int main()
{
int myArray[] = { 2, 3, 4 };
giveMeArray(myArray[2]);
return 0;
}
void giveMeArray(int a)
{
printf("%d", a);
}
Output: 4
Example 2:
#include <stdio.h>
void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8,9, 0};
for (int i=0; i<10;i++)
{
/* Passing addresses of array elements*/
disp (&arr[i]);
}
return 0;
}
OUTPUT:
1 2 3 4 5 6 7 8 9 0
Strings are just char arrays. So, they can be passed to a function in a similar manner as arrays.
#include <stdio.h>
void displayString(char str[]);
int main()
{
char str[50]; printf("Enter string: ");
gets(str);
displayString(str);
// Passing string c to function. return 0;
}
void displayString(char str[])
{
printf("String Output: ");
puts(str);
}
Example-2 :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void strreverse(char *string)
{
int i, len;
char c;
len=strlen(string);
char string2[len+1];
string2[len-i]=c;
}
string2[len+1]='\0';
string=string2;
//printf("%s\n", string);
}
A pointer to a function is passed in this example. As an argument, a pointer is passed instead of a variable
and its address is passed instead of its value. As a result, any change made by the function using the pointer
is permanently stored at the address of the passed variable. In C, this is referred to as call by reference.
Below is the C program to pass arguments to function with pointers:
// Driver code
int main()
{
int a = 10, b = 20;
printf("Values before swap function are: %d, %d\n", a, b);
swap(&a, &b);
printf("Values after swap function are: %d, %d", a, b);
return 0;
}
Output:
In C, recursion is used to solve complex problems by breaking them down into simpler sub-problems.
We can solve large numbers of problems using recursion in C. For example, factorial of a number,
generating Fibonacci series, generating subsets, etc.
Applications of Recursion in C
Recursion is widely used to solve different kinds of problems from simple ones like printing linked
lists to being extensively used in AI. Some of the common uses of recursion are:
Tree-Graph Algorithms
Mathematical Problems
Dynamic Programming
Advantages of C Recursion
2. Some problems are easily solved by using recursion like the tower of Hanoi and tree
traversals.
3. Data structures like linked lists, trees, etc. are recursive by nature so recursive methods are
easier to implement for these data structures.
Disadvantages of C Recursion
As with almost anything in the world, recursion also comes with certain limitations some of which
are:
1. Recursive functions make our program a bit slower due to function call overhead.
2. Recursion functions always take extra space in the function call stack due to separate stack
frames.
In C, a function that calls itself is called Recursive Function. The recursive functions contain a call to
themselves somewhere in the function body. Moreover, such functions can contain multiple
recursive calls.
Types of C Recursion
Examples of Recursion in C
Example 1: C Program to Find the Factorial of a Natural Number using Tail Recursion.
#include <stdio.h>
int factorialTail(int n) {
// Base case
if (n == 1 || n == 0) {
return 1;
} else {
int main() {
int n = 5;
return 0;
Output:
#include<stdio.h>
if(n>0){
n3 = n1 + n2;
n1 = n2;
n2 = n3;
printf("%d ",n3);
printFibonacci(n-1);
} }
int main(){
int n;
scanf("%d",&n);
printf("%d %d ",0,1);
return 0; }
Output:
As can be seen, the length (size) of the array above is 9. But what if there is a requirement to change
this length (size)? For example,
If there is a situation where only 5 elements are needed to be entered in this array. In this
case, the remaining 4 indices are just wasting memory in this array. So there is a
requirement to lessen the length (size) of the array from 9 to 5.
Take another situation. In this, there is an array of 9 elements with all 9 indices filled. But
there is a need to enter 3 more elements in this array. In this case, 3 indices more are
required. So the length (size) of the array needs to be changed from 9 to 12.
Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of a data
structure (like Array) is changed during the runtime.
C provides some functions to achieve these tasks. There are 4 library functions provided by C defined
under <stdlib.h> header file to facilitate dynamic memory allocation in C programming. They are:
1. malloc()
2. calloc()
3. free()
4. realloc()
C malloc() method
The “malloc” or “memory allocation” method in C is used to dynamically allocate a single large
block of memory with the specified size. It returns a pointer of type void which can be cast into a
pointer of any form. It doesn’t Initialize memory at execution time so that it has initialized each
block with the default garbage value initially.
Syntax of malloc() in C
Example of malloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
scanf("%d",&n);
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
else {
ptr[i] = i + 1;
return 0;
Output:
C calloc() method
Syntax of calloc() in C
Example of calloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
n = 5;
if (ptr == NULL) {
exit(0);
else {
// Memory has been successfully allocated
ptr[i] = i + 1;
} }
return 0; }
Output:
C free() method
“free” method in C is used to dynamically de-allocate the memory. The memory allocated using
functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used,
whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by
freeing it.
Syntax of free() in C
free(ptr);
Example of free() in C
#include <stdio.h>
#include <stdlib.h>
int main()
int n, i;
n = 5;
exit(0);
else {
free(ptr);
return 0; }
Output:
C realloc() method
Syntax of realloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
n = 5;
if (ptr == NULL) {
exit(0);
} else {
ptr[i] = i + 1;
}
// Get the new size for the array
n = 10;
ptr[i] = i + 1;
free(ptr);
} return 0; }
Output:
o Automatic
o External
o Static
o Register
extern RAM Zero Global Till the end of the main program Maybe declared
anywhere in the program
static RAM Zero Local Till the end of the main program, Retains value
between multiple functions call
o The visibility of the automatic variables is limited to the block in which they are defined.
The scope of the automatic variables is limited to the block in which they are defined.
o The memory assigned to automatic variables gets freed upon exiting from the block.
Example 1
#include <stdio.h>
int main() {
int a; //auto
char b;
float c;
return 0; }
Output:
Example 2
#include <stdio.h>
int main()
int a = 10,i;
printf("%d ",++a);
int a = 20;
for (i=0;i<3;i++) {
} }
Output:
11 20 20 20 11
o The variables defined as static specifier can hold their value between the multiple function
calls.
o Static local variables are visible only to the function or the block in which they are defined.
o A same static variable can be declared many times but can be assigned at only one time.
o The visibility of the static global variable is limited to the file in which it has declared.
#include<stdio.h>
static char c;
static int i;
static float f;
void main () {
Output:
0 0 0.000000 (null)
Example 2
#include<stdio.h>
void sum()
printf("%d %d \n",a,b);
a++;
b++;
void main() {
int i;
sum(); // The static variables holds their value between multiple function calls.
} }
Output:
10 24
11 25
12 26
Register Storage Class
o The variables defined as the register is allocated the memory into the CPU registers
depending upon the size of the memory remaining in the CPU.
o We can not dereference the register variables, i.e., we can not use &operator for the
register variable.
o The access time of the register variables is faster than the automatic variables.
o The register keyword is used for the variable which should be stored in the CPU register.
However, it is compiler?s choice whether or not; the variables can be stored in the register.
o We can store pointers into the register, i.e., a register can store the address of a variable.
o Static variables can not be stored into the register since we can not use more than one
storage specifier for the same variable.
Example 1
#include <stdio.h>
int main() {
register int a;
// variable a is allocated memory in the CPU register. The initial default value of a is 0.
printf("%d",a);
Output:
Example 2
#include <stdio.h>
int main() {
register int a = 0;
printf("%u",&a); // This will give a compile time error since we can not access the address of
a register variable.
Output:
printf("%u",&a);
^~~~~~
External Storage Class
o The external storage class is used to tell the compiler that the variable defined as extern is
declared with an external linkage elsewhere in the program.
o The variables declared as extern are not allocated any memory. It is only declaration and
intended to specify that the variable is declared elsewhere in the program.
o We can only initialize the extern variable globally, i.e., we can not initialize the external
variable within any block or method.
o An external variable can be declared many times but can be initialized at only once.
o If a variable is declared as external then the compiler searches for that variable to be
initialized somewhere in the program which may be extern or static. If it is not, then the
compiler will show an error.
Example 1
#include <stdio.h>
int main() {
extern int a;
printf("%d",a);
Output
Example 2
#include <stdio.h>
int a;
int main() {
extern int a; // variable a is defined globally, the memory will not be allocated to a
printf("%d",a);
Output
0
Example 3
int a;
int main() {
extern int a = 0;
// this will show a compiler error since we can not use extern and initializer at same time
printf("%d",a);
Output
extern int a = 0;
Example 4
#include <stdio.h>
int main() {
extern int a; // Compiler will search here for a variable a defined and initialized somewhere
//in the program or not.
printf("%d",a);
int a = 20;
Output
20
Example 5
extern int a;
int a = 10;
#include <stdio.h>
int main() {
printf("%d",a); }
Output