C Programming For Problem Solving Module 4
C Programming For Problem Solving Module 4
C Functions
• A piece of code that takes some input, performs computations on those inputs, and provides an output.
4.1 Introduction
A function in C is a set of statements that, when called, perform specific tasks. Functions are the basic building blocks of a C program, providing
modularity and code reusability. The statements in a function are enclosed within {} braces. Functions in C are also known as subroutines or procedures
in other programming languages.
1. Function Declaration
2. Function Definition
3. Function Call
A function declaration specifies the function name, return type, and the number and type of its parameters. It informs the compiler that a function
with the given name is defined elsewhere in the program.
Syntax
108
CHAPTER 4. C FUNCTIONS 109
Examples
The function definition contains the actual statements to be executed when the function is called. In most cases, the function is defined and declared in
a single step.
Syntax
A function call is a statement that directs the program control to execute the function. The function name and parameters are used in the function call.
For example:
#include <stdio.h>
int main() {
int add = sum(10, 30);
CHAPTER 4. C FUNCTIONS 110
Output:
Sum is: 40
Note: A function call is necessary to execute the function. Without it, the function statements will not run.
The return type of a function specifies the type of value that will be returned after execution. When no value needs to be returned, the void type can
be used.
Example
Note: A C function can return only one value. To return multiple values, pointers or structures can be used.
Function arguments, also known as parameters, are data passed to the function when it is called.
Example
4.4.1 Features
• A function is a block of code that can be reused multiple times within a program.
• There are two types of functions: user-defined functions and library functions.
• Function arguments can be passed in two ways: call by value and call by reference.
Modular programming is a technique used to organize a large program into smaller, independent segments called modules. Each module is a separately
named and individually callable program unit. This approach follows the principle of “divide-and-conquer”, allowing complex problems to be broken
down into manageable parts.
• Code Reusability: Modules can be reused across multiple programs or projects, reducing development time and effort.
• Improved Maintainability: Since modules are independent, fixing bugs or making changes becomes easier and less prone to errors.
• Enhanced Readability: Breaking a program into modules improves the clarity and structure of the code, making it easier to understand.
• Independent Development: Different modules can be developed and tested independently, allowing parallel development and better resource
utilization.
• Encapsulation: Modules can hide their internal details from other parts of the program, promoting data security and reducing dependencies.
• Ease of Debugging: Isolating issues becomes simpler as each module can be tested and debugged individually.
CHAPTER 4. C FUNCTIONS 111
5. Integration: Combine all modules to form the complete program and ensure they work seamlessly together.
4.5.4 Conclusion
Modular programming simplifies software development by promoting a structured, organized approach to coding. It enhances productivity, maintainability,
and scalability, making it a preferred methodology for building robust and efficient programs.
2. User-Defined Functions
Library functions are built-in functions provided by the compiler. They are directly usable without being defined by the programmer.
or
These functions are pre-defined in the library of the C compiler and are frequently used in C programs. They are written by the designers of the C
compiler. C supports many built-in functions such as:
• Mathematical functions
Example
#include <math.h>
#include <stdio.h>
int main() {
double number = 49;
double squareRoot = sqrt(number);
printf("The Square root of %.2lf = %.2lf", number, squareRoot);
return 0;
}
Output:
These functions are written by programmers to perform specific tasks. They are not readily available and are created to serve a programmer’s custom
requirements. or User-defined functions are created by the programmer and can be tailored to specific needs.
Example
#include <stdio.h>
int main() {
int a = 30, b = 40;
int res = sum(a, b);
printf("Sum is: %d", res);
return 0;
}
Output:
Sum is: 70
Advantages of Functions in C
Functions in C are a highly useful feature of the language, offering several advantages as outlined below:
• Better memory utilization: Functions reduce the repetition of the same statements in a program.
• Simplified debugging: Functions can be called as many times as needed without any fixed limit.
• Enhanced data protection: Once a function is declared, it can be reused without needing to consider its internal workings.
CHAPTER 4. C FUNCTIONS 113
Disadvantages of Functions in C
• There is memory and time overhead due to stack frame allocation and transfer of program control.
A user-defined function in C is a type of function defined by the programmer to perform a specific task. These functions provide code reusability
and modularity, making programs more efficient and easier to maintain. Unlike built-in functions, their functionality is specified by the user, and no
additional header files are required for their usage.
• Function Prototype: Specifies the function’s name, parameters, and return type to inform the compiler about its existence.
• Function Definition: Contains the actual implementation of the function, including the statements to be executed.
A function prototype, also known as a function declaration, specifies the function’s name, parameters, and return type without containing its body. It
informs the compiler about the function’s existence.
Syntax:
The function definition includes the actual implementation of the function, enclosed within {} braces.
Syntax:
1. Function Parameters: Values passed to the function by the caller. Parameters must match in type and number between the call and definition.
2. Function Body: Statements within {} braces that execute when the function is called.
3. Return Value: The value returned to the caller. If no value is returned, the function type is void.
CHAPTER 4. C FUNCTIONS 114
In C, there are different ways in which parameter data can be passed into and out of methods and functions. Let us assume that a function B() is
called from another function A(). In this case, A is called the caller function and B is called the called function or callee function. The arguments
which A sends to B are called actual arguments, and the parameters of B are called formal arguments.
Terminology
• Formal Parameter: A variable and its type as it appears in the prototype of the function or method.
• Actual Parameter: The variable or expression corresponding to a formal parameter that appears in the function or method call in the calling
environment.
Modes
• IN/OUT: The caller tells the callee the value of the variable, which the callee may update.
Parameter passing techniques in C, such as pass by value and pass by reference, are fundamental for controlling data flow.
1. Pass by Value or Call by Value: : A copy of the argument is passed, and changes in the function do not affect the original value.
2. Pass by Reference or Call by Reference: The address of the argument is passed, allowing changes in the function to reflect in the original
variable.
[Link] by Value
In this method, the values of actual parameters are copied to the formal parameters. Changes inside the function do not affect the original values.
Example
#include <stdio.h>
int main() {
int var1 = 3, var2 = 2;
printf("Before swap: %d, %d\n", var1, var2);
swap(var1, var2);
printf("After swap: %d, %d", var1, var2);
return 0;
}
Output:
Before swap: 3, 2
After swap: 3, 2
Note: If the function call is present after the function definition, the prototype can be omitted.
CHAPTER 4. C FUNCTIONS 115
A function call is used to execute a user-defined function. Arguments are passed inside parentheses.
Syntax:
General Syntax:
function_name(parameter_list);
• The method of calling a function to achieve a specific task is called a function call.
• A function call is essentially invoking a function at the required place in the program to perform a specific task.
Categories of Functions
Example:
// Function prototype
int sum(int, int);
// Function definition
int sum(int x, int y) {
return x + y;
}
// Driver code
int main() {
int x = 10, y = 11;
int result = sum(x, y);
printf("Sum of %d and %d = %d", x, y, result);
return 0;
}
Output:
Sum of 10 and 11 = 21
CHAPTER 4. C FUNCTIONS 116
• When a function has no arguments, it does not receive any data from the calling function.
• Similarly, when it does not return a value, the calling function does not receive any data from the called function.
Example:
[language=C]
#include<stdio.h>
void sum(void);
int main() {
sum();
}
void sum() {
int a = 10, b = 20, sum = 0;
sum = a + b;
printf("Sum = %d", sum);
}
Output:
Sum = 30
• The calling function does not send any data to the called function but accepts the return value.
Example:
[language=C]
#include<stdio.h>
int sum(void);
int main() {
int s;
s = sum();
printf("Sum = %d", s);
}
int sum() {
int a, b, sum = 0;
printf("Enter a and b: ");
scanf("%d %d", &a, &b);
sum = a + b;
return sum;
}
Output:
Enter a and b:
10 20
Sum = 30
Example:
CHAPTER 4. C FUNCTIONS 117
[language=C]
#include<stdio.h>
void sum(float, float);
int main() {
float x, y;
printf("Enter x and y: ");
scanf("%f %f", &x, &y);
sum(x, y);
}
void sum(float a, float b) {
float s = a + b;
printf("Sum = %f", s);
}
Output:
Enter x and y:
1.5 2.5
Sum = 4.000000
• The calling function sends data to the called function and also accepts a return value.
Example:
[language=C]
#include<stdio.h>
int sum(int, int);
int main() {
int x, y, c;
printf("Enter x and y: ");
scanf("%d %d", &x, &y);
c = sum(x, y);
printf("Sum = %d", c);
}
int sum(int a, int b) {
return a + b;
}
Output:
Enter x and y:
10 20
Sum = 30
To process arrays in a large program, they can be passed to functions in two ways:
Example:
CHAPTER 4. C FUNCTIONS 118
[language=C]
#include<stdio.h>
int square(int);
int main() {
int num[5] = {2, 4, 6, 8, 10}, i;
for (i = 0; i < 5; i++) {
square(num[i]);
}
}
int square(int n) {
int sq = n * n;
printf("%d ", sq);
}
Output:
4 16 36 64 100
Example:
[language=C]
#include<stdio.h>
void modify(int[]);
int main() {
int a[5] = {10, 20, 30, 40, 50}, i;
modify(a);
printf("Elements:\n");
for (i = 0; i < 5; i++) {
printf("%d\t", a[i]);
}
}
void modify(int x[]) {
for (int i = 0; i < 5; i++) {
x[i] = x[i] + 5;
}
}
Output:
15 25 35 45 55
Strings are treated as character arrays in C. The rules for passing strings to functions are similar to those for arrays:
• The call must pass the string array name without subscripts.
Example:
[language=C]
#include<stdio.h>
void display(char[]);
int main() {
char str[] = "students";
CHAPTER 4. C FUNCTIONS 119
display(str);
}
void display(char str[]) {
printf("String is: %s", str);
}
Output:
In this method, the memory addresses of actual parameters are passed. Changes made inside the function affect the original values.
Example
#include <stdio.h>
int main() {
int var1 = 3, var2 = 2;
printf("Before swap: %d, %d\n", var1, var2);
swap(&var1, &var2);
printf("After swap: %d, %d", var1, var2);
return 0;
}
Output:
Before swap: 3, 2
After swap: 2, 3
2. Pass by Pointers
This technique uses a pointer. In this method, the memory address (pointer) of a variable is passed rather than the actual value. This allows the
function to access and modify the content at that particular memory location.
#include <stdio.h>
int main()
{
int x = 5;
int* myptr = &x;
modifyVal(myptr);
Output:
• Changes made by one pointer affect other pointers pointing to the same memory location.
• Effective memory management is required using functions like malloc and free.
These techniques are older and were used in earlier programming languages like Pascal, Algol, and Fortran. These are not applicable in high-level
languages.
1. Pass By Result
This method uses out-mode semantics. Before control is transferred back to the caller, the value of the formal parameter is transmitted back to the
actual parameter. This method is also called call by result.
2. Pass By Value-Result
This method uses in/out-mode semantics. It is a combination of Pass By Value and Pass By Result. Before control is transferred back to the caller, the
value of the formal parameter is transmitted back to the actual parameter.
3. Pass By Name
This technique is used in programming languages such as Algol. The symbolic name of a variable is passed, allowing it to be accessed and updated.
For example:
procedure double(x);
real x;
begin
x := x * 2;
end;
• The argument expression is re-evaluated each time the formal parameter is passed.
• The procedure can change the values of variables used in the argument expression.
• Simplifies debugging and testing by breaking tasks into smaller, manageable units.
Iteration Recursion
Code
int main()
{
int x, y, gcd, lcm;
printf("Enter two numbers: ");
scanf("%d%d", &x, &y);
gcd = hcf(x, y);
lcm = (x * y) / gcd;
printf("GCD = %d\n", gcd);
printf("LCM = %d\n", lcm);
return 0;
}
Output
GCD = 4
LCM = 24
4.8 Recursion
Recursion is a method of solving problems where the solution to a problem depends on solutions to smaller instances of the same problem. A recursive
function is a function that calls itself during its execution.
In C programming language, you may have heard of the concept of recursion. Recursion is often considered difficult and complex to understand and
implement.
What is Recursion in C?
Recursion is the process of a function calling itself repeatedly until a given condition is satisfied. A function that calls itself directly or indirectly is
called a recursive function, and such function calls are referred to as recursive calls.
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, such as calculating the factorial of a number, generating a Fibonacci series, generating subsets, etc.
Types of Recursion
• Direct Recursion: A recursive function that invokes itself is said to have direct recursion. For example, the factorial function calls itself, hence
it is called direct recursion.
• Indirect Recursion: A function that calls another function which in turn calls another function, and so on, is said to have indirect recursion.
A function that calls itself is called a Recursive Function. Recursive functions contain a call to themselves somewhere in the function body. These
functions can also contain multiple recursive calls.
1. Base Case:
2. General Case:
The following C program demonstrates recursion to calculate the sum of the first N natural numbers:
#include <stdio.h>
int nSum(int n)
{
// base condition to terminate the recursion when N = 0
if (n == 0) {
return 0;
}
return res;
}
int main()
{
int n = 5;
// calling the function
int sum = nSum(n);
printf("Sum of First %d Natural Numbers: %d", n, sum);
return 0;
}
Output:
Sum of First 5 Natural Numbers: 15
The fundamental of recursion consists of two key elements essential for any recursive function:
CHAPTER 4. C FUNCTIONS 124
The recursion case refers to the recursive call present in the recursive function. It determines the type of recursion and how the problem will be divided
into smaller sub-problems. For example, in the function nSum(), the recursion case is:
f (N ) = N + f (N − 1)
Base Condition
The base condition specifies when the recursion will terminate. It defines the exit point for recursion. For the function nSum(), the base condition is:
if (n == 0) return 0;
It is important to define the base condition before the recursion case, otherwise the recursion might continue indefinitely.
nSum(5) = 5 + nSum(4)
nSum(4) = 4 + nSum(3)
CHAPTER 4. C FUNCTIONS 125
nSum(3) = 3 + nSum(2)
nSum(2) = 2 + nSum(1)
nSum(1) = 1 + nSum(0)
nSum(5) = 5 + 4 + 3 + 2 + 1 + 0 = 15
In C, memory for function calls is managed via the stack. When a recursive function is called, a new stack frame is created for each function call. Each
time a recursive call occurs, a new stack frame is pushed onto the stack, and when the function returns, the stack frame is destroyed.
If a recursive function goes on indefinitely, it may exhaust the memory allocated for the stack. This results in a stack overflow, which is a common
error in recursion.
In general, the recursive function for the factorial problem can be written as:
5! = 5 × 4!
4! = 4 × 3!
3! = 3 × 2!
2! = 2 × 1!
1! = 1 × 0!
0! = 1 (Base Case)
Calculations:
1! = 1 × 0! = 1 × 1 = 1
2! = 2 × 1! = 2 × 1 = 2
3! = 3 × 2! = 3 × 2 = 6
4! = 4 × 3! = 4 × 6 = 24
5! = 5 × 4! = 5 × 24 = 120
Limitations of Recursion
Recursive solutions may involve extensive overhead because they use function calls.
Each time a call is made, memory allocation is used, and if recursion is deep, the program may run out of memory.
Example Programs
int fact(int);
void main() {
int n, res;
printf("Enter the number to find its factorial\n");
scanf("%d", &n);
res = fact(n);
printf("Factorial of %d = %d", n, res);
}
int fact(int n) {
if (n == 0)
return 1;
else
return (n * fact(n - 1));
}
This C program illustrates the concept of indirect recursion. Two functions, functionA() and functionB(), call each other indirectly.
void functionA(int n)
{
if (n < 1) {
return;
}
printf("%d ", n);
n = n - 1;
void functionB(int n)
{
if (n < 2) {
return;
}
int main()
{
// Function call
functionB(20);
return 0;
}
Output:
20 10 9 4 3 1
Recursion is widely used to solve various problems, from simple tasks like printing linked lists to complex problems in fields such as Artificial Intelligence.
Some common applications include:
• Tree-Graph Algorithms
• Mathematical Problems
• Dynamic Programming
• Some problems, like the Tower of Hanoi and tree traversals, are more easily solved with recursion.
• Data structures like linked lists and trees are recursive by nature, so recursive methods are easier to implement for these data structures.
• Recursive functions may make the program slower due to the overhead of function calls.
• Recursive functions consume extra space in the function call stack because of separate stack frames.
4.9 Pointers in C
A pointer is a variable that holds the address of another variable of the same datatype. A pointer variable contains the address of another variable,
which is a location in memory. The value of the pointer variable is stored in another memory location.
A pointer is a variable that stores the memory address of another variable. Instead of holding a direct value, it holds the address where the value is
stored in memory. There are two important operators used in pointer concepts:
• Dereferencing operator (*): Used to declare a pointer variable and access the value stored at the address.
• Address operator (&): Used to return the address of a variable or to assign the address of a variable to a pointer.
For example:
int a = 100;
int *pt = &a;
Here, pt is a pointer, and it can hold the address of variable a. The & symbol is called the reference operator.
Example 1
#include <stdio.h>
int main() {
int m = 100; // integer variable
int *ptr = &m; // pointer variable storing address of m
return 0;
}
Output:
Important Points:
• Printing a pointer with %d format specifier may result in a warning or undefined behavior.
• The memory address format is always in hexadecimal format (starting with 0x).
Example 2
#include <stdio.h>
int main() {
int a = 10; // integer variable
int *ptr; // pointer declaration
ptr = &a; // pointer initialization
return 0;
}
Output:
ptr = 0x7fffa0757dd4
*ptr = 10
• Normal variables store values, whereas pointer variables store the addresses of variables.
• * is used to get the value of the variable that the pointer points to.
Pointer Operations
A. Pointer Declaration
To declare a pointer, use the (*) dereference operator before its name. In pointer declaration, the pointer is declared but not initialized.
B. Pointer Initialization
Pointer initialization involves assigning an initial value to the pointer variable using the (&) address operator.
C. Pointer Dereferencing
Dereferencing a pointer accesses the value stored at the memory address specified by the pointer.
#include <stdio.h>
int main() {
char *s = "santhosh"; // string as pointer
printf("%s", s);
return 0;
}
Output:
santhosh
CHAPTER 4. C FUNCTIONS 130
Types of Pointers in C
Advantages of Pointers
• Can be used to pass information between a function and its reference point.
• Facilitate the implementation of data structures like linked lists and trees.
Disadvantages of Pointers
General Syntax:
data_type *pointer_name;
•
• int *ptr;
The unary operator * is the dereferencing operator or indirection operator. When applied to a pointer, it accesses the value the pointer points to.
Example:
#include <stdio.h>
void main() {
int a = 50;
int *ptr;
ptr = &a;
printf("Value of a: %d", a); // 50
printf("Address of a: %p", ptr); // Address of a
printf("Value at ptr: %d", *ptr); // 50
}
A null pointer is a pointer that does not point to any valid memory address. It can be initialized as:
This indicates that the pointer does not point to any valid reference.
The NULL pointer is a pointer that does not point to any location but NULL. According to the C11 standard:
“An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null
pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to
any object or function.”
NULL expands to an implementation-defined null pointer constant defined in header files like stdio.h, stddef.h, and stdlib.h.
• To initialize a pointer variable when it hasn’t been assigned a valid memory address.
• To check for a null pointer before accessing any pointer variable, enabling error handling.
• To pass a null pointer to a function argument when no valid memory address is needed.
• In data structures like trees and linked lists, to indicate the end.
The pointer can be checked for NULL using the equality operator (==):
ptr == NULL;
int main()
{
// declaring null pointer
int* ptr = NULL;
int main()
{
// declaring dynamic memory for ptr
int* ptr = (int*)malloc(5 * sizeof(int));
return 0;
}
Dereferencing a NULL pointer can cause undefined behavior and may crash.
return;
}
printf("Non-Null Pointer Passed");
}
int main()
{
foo(NULL); // Passing NULL
return 0;
}
Pointer Initialization
Pointer initialization assigns the address of a variable to a pointer variable. The & operator is used to determine the address of a variable. Example:
int x = 5;
int *ptr = &x;
Pointer Arithmetic in C
Pointer arithmetic is the set of valid arithmetic operations that can be performed on pointers. Pointer variables store the memory address of another
variable and do not store any value themselves. As a result, only a few operations are allowed on pointers in C. These operations differ from standard
arithmetic and include:
1. Increment/Decrement of a Pointer
When a pointer is incremented or decremented, the address it stores changes by a value equal to the size of the data type it points to. For example:
• If an int pointer storing the address 1000 is incremented, the new address will be 1004 (size of int is 4 bytes).
• If a float pointer storing the address 1000 is incremented, the new address will also be 1004 (size of float is 4 bytes).
• If a char pointer storing the address 1000 is incremented, the new address will be 1001 (size of char is 1 byte).
CHAPTER 4. C FUNCTIONS 134
#include <stdio.h>
int main() {
int a = 22;
int *p = &a;
printf("p = %p\n", p);
p++;
printf("p++ = %p\n", p);
p--;
printf("p-- = %p\n", p);
float b = 22.22;
float *q = &b;
printf("q = %p\n", q);
q++;
printf("q++ = %p\n", q);
q--;
printf("q-- = %p\n", q);
char c = ’a’;
char *r = &c;
printf("r = %p\n", r);
r++;
printf("r++ = %p\n", r);
r--;
printf("r-- = %p\n", r);
return 0;
}
Adding an integer to a pointer adjusts the address it stores by a value equal to the integer multiplied by the size of the data type.
CHAPTER 4. C FUNCTIONS 135
#include <stdio.h>
int main() {
int N = 4;
int *ptr = &N;
return 0;
}
Similar to addition, subtracting an integer adjusts the pointer address by the integer multiplied by the size of the data type.
#include <stdio.h>
int main() {
int N = 4;
int *ptr = &N;
return 0;
}
Subtracting two pointers of the same type calculates the difference in the number of elements between them. The result is the number of increments of
the pointer type.
#include <stdio.h>
int main() {
int x = 6, N = 4;
int *ptr1 = &N, *ptr2 = &x;
CHAPTER 4. C FUNCTIONS 136
return 0;
}
Pointers can be compared using relational operators (<, <=, >, >=, ==, !=). Comparison checks whether the addresses stored in the pointers satisfy
the condition.
#include <stdio.h>
int main() {
int arr[5];
int *ptr1 = arr;
int *ptr2 = &arr[3];
return 0;
}
Example:
int a = 10;
int *ptr = &a;
ptr = ptr + 1; // Moves to the next memory location based on data type size.
Applications of Pointers in C
Pointers in C are variables that are used to store the memory address of another variable. Pointers allow us to efficiently manage the memory and hence
optimize our program. Below are some major applications of pointers in C.
Prerequisite
The following example demonstrates the use of pointers by swapping two numbers:
CHAPTER 4. C FUNCTIONS 137
#include <stdio.h>
int main() {
int x = 10, y = 20;
swap(&x, &y);
printf("%d %d\n", x, y);
return 0;
}
Output: 20 10
The following example demonstrates the use of pointers to write efficient code:
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printArray(arr, 5);
return 0;
}
Output: 1 2 3 4 5
Note: Passing a large structure without reference creates a copy of the structure, leading to memory inefficiency.
Pointers can be used to access and modify elements of an array. The compiler internally uses pointer arithmetic to access array elements.
#include <stdio.h>
int main() {
int arr[] = {100, 200, 300, 400};
printf("%d ", arr[2]); // Access using index
printf("%d\n", *(arr + 2)); // Access using pointers
return 0;
}
In C, functions can only return a single value. Using pointers, multiple values can be returned from a function.
CHAPTER 4. C FUNCTIONS 138
#include <math.h>
#include <stdio.h>
int main() {
int n = 100;
int sq;
double sq_root;
fun(n, &sq, &sq_root);
printf("%d %f\n", sq, sq_root);
return 0;
}
Output:
10000
10.000000
Pointers enable dynamic memory allocation, allowing memory to be allocated at runtime and freed explicitly when no longer needed.
#include <stdio.h>
#include <stdlib.h>
int* createArr(int n) {
int* arr = (int*) malloc(n * sizeof(int));
return arr;
}
int main() {
int* pt = createArr(10);
free(pt); // Free the allocated memory
return 0;
}
Pointers are often passed to functions to allow access and modification of data.
Call by Value
In call by value, the values of actual parameters are copied into formal parameters. Changes to formal parameters do not affect the actual parameters.
Example:
Call by Reference
In call by reference, the addresses of actual parameters are passed. Changes to formal parameters affect the actual parameters. Example:
Call by Value
• The type of formal parameters should be the same as the type of actual parameters.
• The type of formal parameters should be the same as the type of actual parameters, but they have to be declared as pointers.
Actual Parameters
• Actual parameters are also called the argument list. Example: add(m, n)
• The variables used in the function call are called actual parameters.
• Actual parameters are used in the calling function when a function is invoked.
• Example:
add(m, n)
Formal Parameters
• Formal parameters are also called dummy parameters. Example: int add(int a, int b)
• The variables defined in the function header are called formal parameters.
• Formal parameters are used in the function header of the called function.
• Example:
When arguments are passed without pointers, changes made in the function affect only the local variables. Here’s an example:
#include <stdio.h>
int main() {
int a = 10, b = 20;
swap(a, b);
printf("Values after swap function are: %d, %d", a, b);
return 0;
}
Output:
Passing pointers allows the function to directly modify the variables’ values stored at their memory addresses.
#include <stdio.h>
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:
Function pointers allow dynamic function calls, making the code more modular.
#include <stdio.h>
void fun(int a) {
printf("Value of a is %d\n", a);
}
CHAPTER 4. C FUNCTIONS 141
int main() {
void (*fun_ptr)(int) = &fun; // Declare and initialize function pointer
(*fun_ptr)(10); // Call function via pointer
return 0;
}
Output:
Value of a is 10
The & and * operators can be omitted in some cases for function pointers.
#include <stdio.h>
void fun(int a) {
printf("Value of a is %d\n", a);
}
int main() {
void (*fun_ptr)(int) = fun; // Simplified assignment
fun_ptr(10); // Simplified call
return 0;
}
Output:
Value of a is 10
#include <stdio.h>
int main() {
void (*fptrArr[])(int, int) = { add, sub, mul };
int ch, a = 15, b = 10;
Output Example:
#include <stdio.h>
int main() {
wrapper(fun1);
wrapper(fun2);
return 0;
}
Output:
Fun1
Fun2
The standard library function qsort() uses function pointers for custom comparisons.
#include <stdio.h>
#include <stdlib.h>
int main() {
int arr[] = { 10, 5, 15, 12, 90, 80 };
int n = sizeof(arr) / sizeof(arr[0]);
Output:
5 10 12 15 80 90
Dynamic memory allocation in C provides methods to allocate memory at runtime. This is essential when the size of the data structure is not known at
compile time. The functions malloc(), calloc(), free(), and realloc() are part of the standard library stdlib.h.
CHAPTER 4. C FUNCTIONS 143
Functions
• malloc(): Allocates a block of memory of specified size (in bytes) and returns a pointer to the beginning.
• calloc(): Allocates memory for an array of elements, initializes them to zero, and returns a pointer.
Examples
1. Using malloc()
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n = 5;
free(ptr);
return 0;
}
2. Using calloc()
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n = 5;
free(ptr);
return 0;
}
3. Using realloc()
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n = 5;
n = 10;
ptr = (int *)realloc(ptr, n * sizeof(int));
if (ptr == NULL) {
printf("Memory reallocation failed\n");
return 1;
}
free(ptr);
return 0;
}
4. Using free()
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n = 5;
return 1;
}
free(ptr);
Conclusion
Dynamic memory allocation is a powerful feature in C that allows efficient use of memory. Proper usage of free() ensures there are no memory leaks,
making programs robust and efficient.