Functions
By Paribesh Sapkota
Definition:
A function is a block of code/group of statements/self contained block of statements/ basic building blocks in a program that performs a particular task. It is also known as procedure or subroutine or module, in other programming languages.
To perform any task, we can create function. A function can be called many times. It provides modularity and code reusability.
Advantage of functions
- Code Reusability
By creating functions in C, you can call it many times. So we don’t need to write the same code again and again.
- Code optimization
It makes the code optimized we don’t need
- Easily to debug the program.
Types of Functions
There are two types of functions in C programming:
Library Functions: are the functions which are declared in the C header files such as scanf(), printf(), gets(), puts(), ceil(), floor() etc. You just need to include appropriate header files to use these functions. These are already declared and defined in C libraries. points to be Remembered
System defined functions are declared in header files
System defined functions are implemented in .dll files. (DLL stands for Dynamic Link Library).
To use system defined functions the respective header file must be included.
User-defined functions: are the functions which are created by the C programmer, so that he/she can use it many times. It reduces complexity of a big program and optimizes the code. Depending upon the complexity and requirement of the program, you can create as many user-defined functions as you want.
ELEMENTS OF USER-DEFINED FUNCTIONS :
To use a user-defined function, we first have to understand the different parts of its syntax. The user-defined function in C can be divided into three parts:
- Function Prototype
- Function Definition
- Function Call
C Function Prototype
A function prototype is also known as a function declaration which specifies the function’s name, function parameters, and return type. The function prototype does not contain the body of the function. It is basically used to inform the compiler about the existence of the user-defined function which can be used in the later part of the program.
Syntax
return_type
function_name
(type1 arg1, type2 arg2, ... typeN argN);
We can also skip the name of the arguments in the function prototype. So,
return_type
function_name
(type1 , type2 , ... typeN);
C Function Definition
Once the function has been called, the function definition contains the actual statements that will be executed. All the statements of the function definition are enclosed within { } braces.
Syntax
return_type
function_name
(type1 arg1, type2 arg2 .... typeN argN) { // actual statements to be executed // return value if any }
Note: If the function call is present after the function definition, we can skip the function prototype part and directly define the function.
C Function Call
In order to transfer control to a user-defined function, we need to call it. Functions are called using their names followed by round brackets. Their arguments are passed inside the brackets.
Syntax
function_name(arg1, arg2, ... argN);
Example of User-Defined Function
The following C program illustrates how to use user-defined functions in our program.
// C Program to illustrate the use of user-defined function #include <stdio.h> // Function prototype int sum(int, int); // Function definition int sum(int x, int y) { int sum; sum = x + y; return x + y; } // Driver code int main() { int x = 10, y = 11; // Function call int result = sum(x, y); printf("Sum of %d and %d = %d ", x, y, result); return 0; }
Output
Sum of 10 and 11 = 21
Components of Function Definition
There are three components of the function definition:
- Function Parameters
- Function Body
- Return Value
1. Function Parameters
Function parameters (also known as arguments) are the values that are passed to the called function by the caller. We can pass none or any number of function parameters to the function.
We have to define the function name and its type in the function definition and we can only pass the same number and type of parameters in the function call.
Example
int foo (
int a, int b)
;
Here, a and b are function parameters.
Note: C language provides a method using which we can pass variable number of arguments to the function. Such functions are called variadic function.
2. Function Body
The function body is the set of statements that are enclosed within { } braces. They are the statements that are executed when the function is called.
Example
int foo (int a, int b) {
int sum = a + b;
return sum;
}
Here, the statements between { and } is function body.
3. Return Value
The return value is the value returned by the function to its caller. A function can only return a single value and it is optional. If no value is to be returned, the return type is defined as void.
The return keyword is used to return the value from a function.
Syntax
return
(expression);
Example
int
foo (int a, int b) {
return a + b;
}
Passing Parameters to User-Defined Functions
We can pass parameters to a function in C using two methods:
- Call by Value
- Call by Reference
1. Call by value
In call by value, a copy of the value is passed to the function and changes that are made to the function are not reflected back to the values. Actual and formal arguments are created in different memory locations.
Example
// C program to show use of // call by value #include <stdio.h> void swap(int a, int b) { int temp = a; a = b; b = temp; } // Driver code int main() { int x = 10, y = 20; printf("Values of x and y before swap are: %d, %d\n", x, y); swap(x, y); printf("Values of x and y after swap are: %d, %d", x, y); return 0; }
Output
Values of x and y before swap are: 10, 20 Values of x and y after swap are: 10, 20
Call by Reference
In a call by Reference, the address of the argument is passed to the function, and changes that are made to the function are reflected back to the values.
Example
// C program to implement // Call by Reference #include <stdio.h> void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // Driver code int main() { int x = 10, y = 20; printf("Values of x and y before swap are: %d, %d\n", x, y); swap(&x, &y); printf("Values of x and y after swap are: %d, %d", x, y); return 0; }
Output
Values of x and y before swap are: 10, 20 Values of x and y after swap are: 20, 10
return and void statements
return statement
One of the main features of the function is that it can return a value to the calling function. For this, a return keyword is used. So, return keyword return the program control from a function to the calling function.
Syntax
return expression;
A function definition can contain multiple return statements. However, only one gets executed.
Example
int great(int a, int b) { if (a>b) return a; else } return b;
// Write a program to print the greatest number between two numbers using function #include<stdio.h> int great(int, int): void main() { int a,b,c; printf("\nEnter two numbers:"); scanf("%d%d",&a,&b); c- great(a,b); printf("\ngreatest number= %d",c); int great(int a,int b) { if(a>b) return(a); else } return(b);
//Write a program to print the smallest number among three numbers using function. #include<stdio.h> int small(int, int,int); void main() int a,b,c,d; { printf("\nEnter three numbers:"); scanf("%d%d%d",&a,&b,&c); dsmall (a,b,c); printf("\nsmallest number= %d",d); int small(int a, int b,int c) { if(a<b && a<c) return(a): else if(b<c) return(b); else return(c); }
void statement
If a function does not return a value then we say that the function’s return type is void. So, no expression is present if a function return type is void. If a return keyword is used, then it is used to transfer the control at the end of the function.
Example
void evenodd(int n) { if (n%2==0) printf("%d is even number", n); else printf("%d is odd number", n);
//Write a program to check whether the entered number is odd or even using function. #include<stdio.h> void evenodd(int); void main() { int n; printf("\nEnter a number"); scanf("%d",&n); evenodd(n); } void evenodd(int n) { if(n%2==0) printf("%d is even number",n); } else { printf("%d is odd number",n); }
Concept of Recursion
Recursion can be regarded as the ability of function defining an object in terms of a simpler case of itself. It is a process by which a function calls itself repeatedly, until some specific condition has been satisfied. For the problem to solve recursively two conditions must be satisfied:
The function should call itself.
The problem statement must include a stopping condition.
//Write a program to calculate sum of n natural numbers using recursion. #include<stdio.h> int sum(int); void main() (int n,f; printf("Enter last number"); scanf("%d",&n); f=sum(n); printf("Sum is %d",f); } int sum(int n) if (n <= 0) { return 0; else return(n+sum(n-1)); }
//Write a program to calculate factorial using recursive function #include<stdio.h> int fact(int); void main() { int a,f; printf("\nEnter a number"); scanf("%d",&n); f=fact(n); printf("\nfactorial of %d is %d", n.f); int fact(int n) { if(n <= 1) return(1); } else { return(n*fact(n-1)); }
From the above program of factorial, the factorial of a number n is expressed as a series of repetitive multiplication as
Factorial of n = n(n – 1)(n – 2)(n – 3) ………….1
Example
Factorial of 3=3^ * 2^ * 1 = 6
Let us see how the recursion works. Assume n = 3 Since the value of n is not less thar 1, the statement
fact = n*fact(n-1);
will be executed with n = 3 That is,
fact=3* fact(2);
will be evaluated. The expression on the right hand side includes a call to fact with n-2. This will return the following value:
2. fact(1);
Once again, fact is called with n 1. This time, the function returns 1. The sequence of operations can be summarized as follows:
fact-3fact(2)
-3.2 fact(1)
-321
-6
Types of Functions
Functions are of two types: Library (built-in) function and user defined function.
1. Library (built-in) function: C has the facility to provide some library function to the programmer for doing some operations. As an example C has a mathematical function which is used for finding out the square root of any number, string library functions are used for string operations, as example strlen() is used to find out the length of the string and strcmp() is used for comparison of two strings. These operations are programmed and stored as library functions, so that they can be called by any program.
Mathematical functions are called by using the preprocessor directive
#include<math.h> and string library functions are called by #include<string.h>
Example
Program to find the square root of any number
#include<stdio.h> #include<math.h> void main() (int n; printf("Enter the number:"); scanf("%d",&n); printf("\nThe square root of %d is %f",n,sqrt(n)); /*sqrt() library function */
User-defined Function: Library functions provide the facility for doing some predefined operations. User can also create functions for doing any specific task of the program. Such functions are called user-defined functions.
Categories of User-defined function
Function returning value and passing arguments: Here, an argument is passed from the calling function to the called function and there will also be return statement in the called function.
#include<stdio.h> int sum(int,int); //function prototype void main() { int a.f: printf("\nEnter two numbers"); scanf("%d%d",&a,&b); f=sum(a,b); printf("\nSum is %d",f); int sum(int a, int b) { int c: c=a+b; return (c); }
Function returning no value but passing arguments: Here, an argument is passed from the calling function to the called function but there is no need of return statement in the called function.
#include<stdio.h> void sum(int,int); //function prototype void main() { int a.b.f: printf("\nEnter two numbers:"); scanf("%d%d",&a,&b); sum(a,b); void sum(int a.int b) { int c: c=a+b; printf("\nSum is %d",c);
Function returning value and passing no arguments: Here, an argument is not passed from the calling function to the called function but there is return statement in the called function.
#include<stdio.h> int sum(); //function prototype void main() { clrscr(); int f; f=sum(); printf("\nSum is %d",f); } void sum() { int a,b,c; printf("\nEnter two numbers"); scanf("%d%d",&a,&b); c=a+b; return (c); }
Function returning no value and passing no arguments: Here, an argument is not passed from the calling function to the called function and there is no return statement in the called function.
#include<stdio.h> void sum(); //function prototype void main() { sum(); void sum() int a,b,c; printf("\nEnter two numbers"); scanf("%d%d",&a,&b); c=a+b; printf("\nSum is %d",c); }
Nested functions
functions can be defined inside other functions. These are called nested functions. Here are some important points about nested functions:
- Scope:
- A nested function is only accessible within the function in which it is defined. It cannot be called from outside the function.
- Conversely, the outer function can access variables and functions defined within the nested function.
- Example:
#include <stdio.h> void outerFunction() { void innerFunction() { printf("This is the inner function\n"); } printf("This is the outer function\n"); innerFunction(); } int main() { outerFunction(); return 0; }
- Use Cases:
- Nested functions are useful when you want to encapsulate functionality that is only needed within a specific function.
- They help in avoiding namespace pollution by restricting the visibility of a function to the outer function only.
- They improve code organization and readability by keeping related functions close to each other.
- Limitations:
- Nested functions are not standard C. They are a GNU C extension and may not be supported by all compilers.
- They should be used judiciously as they can make code less portable and harder to understand.
Pass Array to Functions
the whole array cannot be passed as an argument to a function. However, you can pass a pointer to an array without an index by specifying the array’s name.
Arrays in C are always passed to the function as pointers pointing to the first element of the array.
Syntax
In C, we have three ways to pass an array as a parameter to the function. In the function definition, use the following syntax:
return_type foo (
array_type array_name[size],
...);
Mentioning the size of the array is optional. So the syntax can be written as:
return_type foo (
array_type array_name[]
, ...);
In both of the above syntax, even though we are defining the argument as array it will still be passed as a pointer. So we can also write the syntax as:
return_type foo (
array_type* array_name,
...);
Example 1: Checking Size After Passing Array as Parameter
// C program to pass the array as a function and check its size #include <stdio.h> #include <stdlib.h> // Note that arr[] for fun is just a pointer even if square // brackets are used. It is same as // void fun(int *arr) or void fun(int arr[size]) void func(int arr[8]) { printf("Size of arr[] in func(): %d bytes", sizeof(arr)); } // Drive code int main() { int arr[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; printf("Size of arr[] in main(): %dbytes\n", sizeof(arr)); func(arr); return 0; }
Output
Size of arr[] in main(): 32bytes Size of arr[] in func(): 8 bytes
As we can see,
- The size of the arr[] in the main() function (where arr[] is declared) is 32 bytes which is = sizeof(int) * 8 = 4 * 8 = 32 bytes.
- But in the function where the arr[] is passed as a parameter, the size of arr[] is shown as 8 bytes (which is the size of a pointer in C).
It is due to the fact that the array decays into a pointer after being passed as a parameter. One way to deal with this problem is to pass the size of the array as another parameter to the function. This is demonstrated in the below example.
Printing Array of Characters (String) using Function
// C Program to print the string using a function #include <stdio.h> // function to print the string void printString(char* str) { printf("Array of Characters: "); int i = 0; while (str[i] != '\0') { printf("%c ", str[i]); i++; } } // Driver program int main() { char arr[] = "String"; printString(arr); return 0; }
Output
Array of Characters: S t r i n g
As we can see, we were able to deduce the end of the string (character array) using a NULL Character. Moreover, the %s specifier in printf() function uses the same principle so we can directly use this to print string.
Why can’t we use NULL to terminate the integer or float array?
In C, the null by default is equivalent to 0. So if we want to use NULL as an ending point for an integer or float array, we won’t be able to use 0 as a value of the array element. In some specific cases, it may work but in general, it is meaningless to sacrifice one of the most commonly used digit for this purpose.
Passing Arguments by Address
Passing arguments by address (also known as passing arguments by reference) allows a function to modify the original value of a variable by passing its memory address. In C, this is done using pointers.
Here’s how passing arguments by address works:
- Definition of Function:
- The function must accept a pointer as an argument.
- Inside the function, the pointer is used to access the memory location of the variable.
- Call to Function:
- When calling the function, you pass the address of the variable as an argument.
- Example:
#include <stdio.h> // Function to increment a variable using pass by address void increment(int *x) { (*x)++; // Increment the value stored at the address pointed to by x } int main() { int num = 10; // Before calling the function printf("Before increment: %d\n", num); // Passing the address of num to the function increment(&num); // After calling the function printf("After increment: %d\n", num); return 0; }
output
Before increment: 10
After increment: 11
In this example, increment()
function takes a pointer *x
as an argument. Inside the function, we use (*x)
to access the value stored at the memory location pointed to by x
and increment it.
Passing Arguments by Value
Passing arguments by value involves passing a copy of the variable to the function. This means that changes made to the parameter inside the function do not affect the original variable.
Here’s how passing arguments by value works:
- Definition of Function:
- The function accepts the variable itself as an argument.
- Call to Function:
- When calling the function, you pass the value of the variable as an argument.
- Example:
#include <stdio.h> // Function to increment a variable using pass by value void increment(int x) { x++; // Increment the copy of the value } int main() { int num = 10; // Before calling the function printf("Before increment: %d\n", num); // Passing the value of num to the function increment(num); // After calling the function printf("After increment: %d\n", num); return 0; }
output
Before increment: 10
After increment: 10
In this example, increment()
function takes an integer x
as an argument. Inside the function, changes made to x
do not affect the original variable num
.
Storage Class
The period of time during which memory is associated with a variable is characterized by storage classes. So, storage class of a variable indicates the allocation of space to variable by the compiler. Generally C supports four storage classes automatic, external, register and static.
Automatic storage class: The keyword auto is used to define automatic variable. Variables declared within function bodies are automatic by default. When a block is entered, the system allocates memory for the automatic variables. Within that block, these variables are defined and are considered “local” to the block. So, the value of these variables is lost. If the block is reentered, the system reallocates memory, but the previous values are unknown.
Example
#include<stdio.h> void show(); void main() (show(); show(); show(); void show() { auto int n=5; printf("\nNumber %d",n); n=n+5;
Output of this program will be:
Number 5
Number 5
Number 5
External storage class: The keyword extern is used to define external type variable. The external storage class is used to transmit information across the blocks and functions. When a variable is declared outside function storage is permanently assigned. Such a variable is considered to be global to all functions declared after it.
Example
#include<stdio.h> extern int a = 1 b = 2j int show(); void main() int k; k-show(); printf("\n%d",k); printf f(^ a=\%d backslash tb =\%d^ ,a,b); int show() {int a,b; a = b = 4 return(a+b);
Output is 8
a = 1
b = 2
Static storage class: The keyword static is used to define static type variable. A value is said to be static if it is allocated storage at the beginning of the segment and the storage remains allocated until the program execution terminates.
Example
#include<stdio.h> void show(); void main() show(); show(); show(); void show() static int n = 5 printf("\nNumber %d";n n = n + 5 }
Output of this program will be:
Number 5 Number 10
Number 15
Register storage class: The keyword register is used to define register type variable. The use of the register storage class is an attempt to improve execution speed. It is used only for frequently used variables only (that is limited either two or three).
Example
#include<stdio.h> #include<conio.h> void show(); void main() show(); void show() [ register int n=5,i; for(i=1;i<=40;i++) { printf("\nNumber %d",n); n=n+5; getch();
Output will be:
Number 5
Number 10
Number 200
scope visibility and lifetime of variables
Scope, visibility, and lifetime of variables in C are closely interconnected concepts, yet each has distinct characteristics. Scope defines the area within a C program where a variable can be used. Visibility pertains to whether a variable can be accessed within a particular scope. Lifetime refers to the duration a variable remains in the system’s memory.
Let’s define the concepts of scope, visibility, and lifetime for a variable:
Scope refers to the region within a program where a variable can be used. Essentially, it is the section of code where the variable is accessible. There are four types of scope in C:
– File scope
– Block scope
– Function scope
– Prototype scope
Visibility of a variable denotes whether it can be accessed in a particular region of code or throughout the entire program.
Lifetime of a variable indicates the duration for which the variable occupies space in the system’s memory. It can be categorized into three types:
– Static lifetime
– Automatic lifetime
– Dynamic lifetime
Here are the four types of variable scope in C:
1. File Scope
Variables with file scope are accessible throughout the entire file or program. This means they have a global scope and can be used by every function and block within the program.
#include <stdio.h> // variable with file scope int x = 10; void func() { // x is available in func() function, // x now equals 10 + 10 = 20 x += 10; printf("Value of x is %d\n", x); } int main() { func(); // x is also available in main() function x += 30; // x now equals 20 + 30 = 50 printf("Value of x is %d", x); return 0; }
Explanation : A global variable x is declared having file scope. main() function and func() function are able to access the variable x because it has file scope. In the code, first we have increased the value of x by 10 (x = 20 now) and then by 30 (x = 50 now), and we can see from the output that x preserves its value 20 after the changes made in the function func() because it has file scope.
2.Block Scope
Variables with block scope are limited to the block of code in which they are defined, which is enclosed in curly braces `{}`. These variables are not accessible outside this block, and their memory is released once the block’s execution is complete.
#include <stdio.h> int main() { int a = 5; int b = 10; // inner block of code having block scope { int sum = a + b; printf("Sum of a and b: %d", sum); } // the below statement will throw an error because, // sum variable is not available outside the scope of above block, // printf("Sum of a and b: %d", sum); return 0; }
Explanation : In the above program, the sum variable has block scope, we can’t access the sum variable outside this block where sum is declared. If we uncomment the printf(“Sum of a and b: %d”, sum); statement then the compiler will throw an error of undeclared sum variable in the current scope.
3. Function Scope
Variables with function scope are declared within a function and are accessible only within that function. Their scope begins with the opening curly brace `{` and ends with the closing curly brace `}` of the function. Memory for these variables is allocated when the function is called and is released when the function execution completes and returns a value, at which point the variables go out of scope and are removed from memory.
#include <stdio.h> void findAge() { // the age variable is not accessible outside the function findAge() // as it is having local scope to the function i.e. function scope int age = 18; } int main() { printf("Age is %d", age); return 0; }
Explanation : We can see in the output that a compilation error is thrown to us because we are using an age variable outside the function from where it is declared. Compiler has thrown an error because age variable is not available outside the function as age variable only has function scope.
4. Function Prototype Scope
Variables with function prototype scope are declared as parameters in a function’s definition. Similar to function scope variables, these parameters are allocated memory when the function is called and are deleted once the function execution ends.
#include <stdio.h> // variables a and b are available only inside the function and // both variables have function prototype scope int findSum(int a, int b) { return a + b; } int main() { int sum = findSum(3, 5); printf("Sum of 3 and 5 is %d", sum); return 0; }
Explanation : When the findSum() function is invoked, space for variables a and b is allocated in the system’s memory. Variables a and b are findSum() function parameters and these variables have function prototype scope, we can access these variables only in the function definition and not outside of it.
Local Variables
Variables declared within a function or an inner block are known as local variables. They are confined to the scope of that function or block and can only be used within that specific area.
#include <stdio.h> int main() { int sum = 0; // inner block of code having block scope { int a = 5; int b = 10; } // this statement will throw an error because a and b are not available outside the above block of code sum = a + b; return 0; }
Global Variables
Variables declared outside of all functions are known as global variables. These variables have file scope, meaning they can be accessed from anywhere in the program. They remain in memory for the entire duration of the program’s execution.
#include <stdio.h> // global variable int side = 10; int main() { int squareArea = side * side; printf("Area of Square : %d", squareArea); return 0; }