[go: up one dir, main page]

0% found this document useful (0 votes)
23 views25 pages

Unit 5 - Function - Part - 1

Uploaded by

Yam Raj Bohara
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views25 pages

Unit 5 - Function - Part - 1

Uploaded by

Yam Raj Bohara
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

Unit 5 - Function

In C programming, a function is a self-contained block of code that performs a


specific task.
Functions provide modularity, allowing you to break down your program into
smaller, manageable parts, which can be easier to understand, debug, and maintain.
Example:
● calculate the area of a circle
● calculate the average of two numbers
Dividing a complex problem into smaller chunks makes our program easy to
understand and reuse.

Advantage of functions in C
There are the following advantages of C functions.

Code Reusability: Functions promote reusability, eliminating the need to rewrite


the same logic multiple times.

Modularity: Dividing a program into functions makes it easier to manage and


debug.

Ease of Maintenance: Changes in the code can be made independently within


specific functions without affecting the rest of the program.

Code Readability: Functions improve the clarity and readability of a program by


structuring it into smaller, logical parts.

Reduced Code Redundancy: Functions minimize redundant code, saving


development time and reducing errors.

However, Function calling is always overhead in a C program.


Types of function

There are two types of function in C programming:


● Standard library functions
● User-defined functions

Standard library functions


The standard library functions are built-in functions in C programming. These
functions are defined in header files. For example,
● The printf() is a standard library function to send formatted output to the screen
(display output on the screen). This function is defined in the stdio.h header file.

Hence, to use the printf() function, we need to include the stdio.h header file using
#include <stdio.h>.
● The sqrt() function calculates the square root of a number. The function is
defined in the math.h header file.

User-defined functions

You can also create functions as per your need. Such functions created by the user
are known as user-defined functions.
How user-defined function works?
#include <stdio.h>
void functionName()
{
... .. ...
... .. ...
}

int main()
{
... .. ...
... .. ...
functionName();
... .. ...
... .. ...
}

The execution of a C program begins from the main() function.


When the compiler encounters functionName();, control of the program jumps to
void functionName()
And, the compiler starts executing the codes inside functionName(). The control of
the program jumps back to the main() function once code inside the function
definition is executed.

Example: User-defined function


Here is an example to add two integers. To perform this task, we have created an
user-defined addNumbers().
#include <stdio.h>
int addNumbers(int a, int b); // function prototype
int main()
{
int n1,n2,sum;
printf("Enters two numbers: "); scanf("%d %d",&n1,&n2);
sum = addNumbers(n1, n2); // function call printf("sum = %d",sum);
return 0;
}
int addNumbers(int a, int b) // function definition
{
int result; result = a+b;
return result;// return statement
}
Output:
Write on your own…
Function Declaration and Definition:
In C, a function is declared before it is used. The declaration specifies the
function's name, return type, and parameters (if any). The function definition
provides the implementation of the function.

// Function declaration
int add(int a, int b);

// Function definition
int add(int a, int b) {
return a + b;
}
Function Structure:
A function in C typically consists of a function header, which includes the return
type, function name, and parameters (if any), followed by the function body
enclosed in curly braces `{}`.
return_type function_name(parameters) {
// Function body
}

Function Call:
To use a function, you simply call it by its name and provide any necessary
arguments. The function call can be used as part of an expression or as a
standalone statement.
int result = add(3, 5); // Calling the add function

Return Statement:
A function can return a value using the `return` statement. The return type in the
function declaration specifies the type of value that the function returns.
int add(int a, int b) {
return a + b;
}

Function Parameters:
Functions can take zero or more parameters, which are variables used to pass
values into the function. Parameters are specified in the function declaration and
definition.
int add(int a, int b) {
return a + b;
}
Function declarations are also called prototypes:
A function prototype is a declaration of the function signature (return type, name,
and parameters) without providing the function body. It informs the compiler about
the function's existence and allows you to use the function before it's defined.
// Function prototype
int add(int a, int b);

// Function definition
int add(int a, int b) {
return a + b;
}
Example:
Here's a simple example demonstrating the use of functions to perform addition:
#include <stdio.h>
int add(int a, int b); // Function declaration
int main() {
int result = add(3, 5); // Function call
printf("Result: %d\n", result);
return 0;
}
// Function definition
int add(int a, int b) {
return a + b;
}
Functions are an essential part of C programming, enabling code reuse, abstraction,
and organization. They allow you to write modular and maintainable code by
breaking down tasks into smaller, manageable units.

Advantages of Function (In detail, for self-study)


In C programming, functions play a vital role in structuring code and enhancing its
readability, maintainability, and reusability. Here are the advantages of using
functions specifically in C:

1. Modularity: Functions allow you to break down a large program into smaller,
more manageable modules. Each function can encapsulate a specific task or
functionality, making the overall program structure more organized and easier to
understand.

2. Code Reusability: Once a function is defined, it can be called multiple times


from different parts of the program. This promotes code reuse, as you can use the
same function to perform a specific task without duplicating code.
3. Abstraction: Functions provide an abstraction layer by hiding the
implementation details of a task behind a function interface. Users of the function
only need to know how to use it (function signature), rather than understanding its
internal workings.

4. Encapsulation: Functions encapsulate related operations into a single unit,


allowing you to isolate different parts of the program from each other. This reduces
complexity and makes it easier to manage and maintain code.

5. Separation of Concerns: By dividing a program into smaller functions, each


function can focus on a specific concern or functionality. This separation of
concerns improves code clarity and makes it easier to identify and fix bugs or
make changes.

6. Ease of Testing: Functions make it easier to test individual components of a


program in isolation. You can write unit tests for each function to ensure that it
behaves as expected, which simplifies the debugging process and improves overall
code quality.

7. Optimization: Functions allow you to optimize specific parts of a program


without affecting the rest of the code. By focusing on optimizing critical functions
or algorithms, you can improve the overall performance of the program.

8. Function Prototypes: In C, function prototypes declare the function signature


before its actual definition. This allows you to use functions before they are
defined, enabling better code organization and facilitating inter-function
communication.

9. Standard Library Functions: C provides a rich set of standard library


functions that perform common tasks, such as input/output operations, string
manipulation, and mathematical calculations. These functions save time and effort
by providing pre-defined solutions to common problems.

10. User-defined Functions: In addition to standard library functions, you can


define your own functions tailored to the specific requirements of your program.
This allows you to create custom functionalities and extend the capabilities of the
C language.
Overall, functions are a fundamental feature of C programming that promote code
organization, reusability, and maintainability. By breaking down a program into
smaller, modular components, functions make it easier to develop, test, and
maintain complex software systems.
Function Call and Definition

In C programming, a function call is how you instruct the program to execute a


specific block of code encapsulated within a function. Here's a breakdown of
function calls and function definitions:

Function Definition:
A function definition consists of the function signature (return type, function name,
and parameters) followed by the function body, which contains the code to be
executed when the function is called.
return_type function_name(parameters) {
// Function body
}

For example:
// Function definition
int add(int a, int b) {
return a + b;
}

Function Call:
A function call is the actual invocation of a function in your program.
To call a function, you use its name followed by parentheses, and you may pass
arguments (if the function requires them).
return_type result = function_name(arguments);
For example:
// Function call
int sum = add(3, 5);
Example:
Putting it all together, here's a complete example demonstrating a function
definition and its call:
#include <stdio.h>

// Function definition
int add(int a, int b) {
return a + b;
}

int main() {
// Function call
int result = add(3, 5);
printf("Result: %d\n", result);
return 0;
}
When you run the program, it will output:
Result: 8
This demonstrates how function calls and definitions work together in C
programming to structure and execute code efficiently.
Nested functions and recursive functions

Nested functions and recursive functions are both advanced concepts in


programming that involve functions within functions.

Nested Functions:
Nested functions are functions defined inside other functions.
In C programming, nested functions are not directly supported by the language
standard, but they can be emulated using function pointers or by defining functions
inside other functions using certain compiler extensions, such as GNU C
Extensions.
Here's an example using function pointers:
#include <stdio.h>
// Outer function
void outer() {
printf("This is the outer function\n");

// Nested function (emulated using function pointer)


void inner() {
printf("This is the nested function\n");
}

// Call the nested function


inner();
}
int main() {
outer();
return 0;
}

In this example, `inner` is defined inside the `outer` function. However, this code
may not work with all compilers and is generally considered non-portable.
Nested functions provide a way to encapsulate functionality within a limited scope,
but they are less commonly used due to portability concerns.
In standard C, you cannot define a function within another function.
While you can declare a function within a function in C, it is not considered a true
nested function as it doesn't have access to the local variables of the containing
function.
Note:
In C, we can declare a function inside another function, but it’s not treated as a
nested function. True nested functions, which can access local variables of the
enclosing function, are not supported in C. Instead, functions can only access
global variables, static variables, or their own local variables. Attempting to define
a nested function in C will result in a compile-time error.

// C program to illustrate the concept of Nested function.


#include <stdio.h>
int main(void)
{
printf("Main");
int fun()
{
printf("fun");
// defining view() function inside fun() function.
int view()
{
printf("view");
}
return 1;
}
view();
}

Output:
Compile time error: undefined reference to `view'
An extension of the GNU C Compiler will only allow this.
The declarations of nested functions under GCC’s extension need to be prefix/start
with the auto keyword.
Recursive Functions:
Recursive functions are functions that call themselves either directly or indirectly.
They are particularly useful for solving problems that can be broken down into
smaller, similar subproblems.
The recursive functions perform certain tasks dividing them into various subtasks.
Recursive functions typically consist of two parts: a base case that defines the
termination condition, and a recursive case that calls the function again with
modified arguments.
Here's an example of a recursive function to calculate the factorial of a non-
negative integer:
#include <stdio.h>
// Recursive function to calculate factorial
unsigned long long factorial(int n) {
// Base case: factorial of 0 or 1 is 1
if (n == 0 || n == 1) {
return 1;
}
// Recursive case: factorial of n is n * factorial(n - 1)
else {
return n * factorial(n - 1);
}
}

int main() {
int n = 5;
printf("Factorial of %d is %llu\n", n, factorial(n));
return 0;
}
In this example, the `factorial` function calls itself with a smaller argument (`n - 1`)
until it reaches the base case (`n == 0` or `n == 1`), at which point it terminates and
returns a value.
Recursive functions are powerful but can lead to stack overflow errors if not
implemented properly with appropriate termination conditions.
Both nested functions and recursive functions are advanced programming concepts
that require careful consideration and understanding of their behavior and potential
limitations.

Example: The Fibonacci Series


Let us take a look at an example where we generate a Fibonacci series for any
available function by utilising the recursive function in a code:
#include <stdio.h>
int fibonacci(int x) {
if(x == 0) {
return 0;
}
if(x == 1) {
return 1;
}
return fibonacci(x-1) + fibonacci(x-2);

}
int main() {
int x;
for (x = 0; x < 10; x++) {
printf(“%d\t\n”, fibonacci(x));
}
return 0;
}
The compilation and execution of the code mentioned above will generate the
result as follows:
0
1
1
2
3
5
8
13
21
34
The Allocation of Memory in Recursive Methods

In recursive functions, each recursive call leads to the creation of a new stack
frame. A stack frame is a memory structure that stores the local variables, return
address, and other information related to the current function call.

Key Points:

1. Stack Frames: Each recursive call creates a new stack frame. When a
function is called, the program saves its current state (local variables, the
return address, etc.) in the stack, and when the function returns, this stack
frame is destroyed.
2. Memory Usage: As recursion deepens, more and more stack frames are
created, consuming memory. When the recursion reaches the base case
(termination condition), the function starts returning values, and the stack
frames are destroyed one by one.

Recursive methods use additional memory to store the state of each


recursive call. For deep recursion, this can lead to significant memory
consumption and even stack overflow if the recursion depth is too large.

Example: Recursive Function and Memory Allocation


#include <stdio.h>
int display(int x) {
if (x == 0) {
return 0; // termination condition
} else {
printf("%d ", x); // print the current value of x
return display(x - 1); // recursive call
}
}
int main() {
int result = display(4); // call the recursive function with x = 4
return 0;
}

Explanation of Code

In this example, the function display(int x) recursively prints the value of x and
then decrements x until it reaches the base case where x == 0. Here's a breakdown
of what happens when x = 4:

1. First Call (display(4)):


o The function prints 4.
o It calls display(3) (recursive call).
2. Second Call (display(3)):
o The function prints 3.
o It calls display(2) (recursive call).
3. Third Call (display(2)):
o The function prints 2.
o It calls display(1) (recursive call).
4. Fourth Call (display(1)):
o The function prints 1.
o It calls display(0) (recursive call).
5. Fifth Call (display(0)):
o The function returns 0 because it meets the base case (x == 0).

While the function returns 0 at the base case, the return value is not used in this
program. The main purpose of the function is to print the values of x.
The Disadvantages of Recursion Processes in C
Recursive programs are generally slower than non-recursive programs because
each recursive call requires additional overhead. Every time a function calls itself,
the program must save the current state (i.e., local variables, return address, etc.)
onto the call stack. This adds extra time and space complexity as each function call
needs to be pushed onto the stack and later popped off when returning from the
function.

This overhead comes from:

1. Function Call Overhead: Each recursive call requires saving the state of
the current function, which includes storing local variables, return addresses,
and other contextual information. This additional work increases the time
complexity of recursive programs.
2. Memory Consumption: Each recursive call consumes stack memory to
store the function's state. If the recursion depth is high, the memory
consumption can grow significantly, possibly leading to stack overflow in
extreme cases.

In contrast, non-recursive programs do not require maintaining a series of function


calls. They typically use loops or other constructs to achieve repetition, which
doesn’t require saving intermediate states. As a result, non-recursive programs use
less memory and are often faster.

Frequently Asked Questions


Q1 How does recursion work?
In C, recursion occurs when a function calls itself. Recursion continues until it
meets a specified condition to stop further calls, commonly implemented using an
if-else or similar branching statement. One branch typically makes a recursive call,
while the other terminates the recursion.
Defining a proper exit condition (base case) is crucial. Without it, recursion may
lead to an infinite loop or a stack overflow.
Recursive functions are useful for solving mathematical problems like generating
the Fibonacci series, calculating factorials, or implementing algorithms like
quicksort and mergesort.
Q2 What is a recursive function in C?

A recursive function in C is a function that calls itself to solve a problem by


breaking it into smaller sub problems. It includes two key components:

1. Base Case: The condition at which the recursion stops. This ensures that the
function eventually terminates.
2. Recursive Case: The part of the function where it calls itself to solve
smaller instances of the problem.

The function repeatedly executes its recursive case until the base case is satisfied,
at which point the recursion stops, and the final result is returned. Recursive
functions follow this structured format and are widely used for problems like
factorial calculation, Fibonacci series generation, and divide-and-conquer
algorithms.

Q3 How do the recursive functions get allocated with memory in C?


In C, each recursive call creates a new stack frame that holds the function's local
variables and state. This stack frame is stored in the call stack. When a function
makes a recursive call, a new copy of the function is pushed onto the stack, with
each call having its own set of local variables.
Once the base case is reached and the function returns, its stack frame is removed,
and control passes back to the previous recursive call. This process continues until
all recursive calls have returned their values, at which point all stack frames are
removed.
Because each recursive call has its own stack frame, managing memory in
recursion can be complex. If the recursion depth is too large, it can lead to stack
overflow due to excessive memory usage.
Practice Problems on Recursion in C
1. What would be the output obtained out of the program mentioned below if we
input a value of 12?

#include <stdio.h>
int fibonacci(int);
int main() {
int x, a;
printf("Please enter the preferred value of the variable x: ");
scanf("%d", &x);
a = fibonacci(x);
printf("%d\n", a);
return 0;
}

int fibonacci(int x) {
if (x == 0) {
return 0;
} else if (x == 1) {
return 1;
} else {
return fibonacci(x - 1) + fibonacci(x - 2);
}
}
A. Please enter the preferred value of the variable x?12
89
B. Please enter the preferred value of the variable x: 12
120
C. Please enter the preferred value of the variable x is?12
124
D. Please enter the preferred value of the variable x is:12
144

Answer: D. Please enter the preferred value of the variable x?12


144

2. What would be the output obtained out of the program mentioned below?

#include <stdio.h>
int fibo(int x) {
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
return fibo(x - 1) + fibo(x - 2); // Corrected the minus sign
}
int main(void) {
int x;
printf("The calculated Fibonacci sequence would be:\n");
for (x = 0; x < 10; x++) {
printf("%d \t", fibo(x)); // Print the Fibonacci sequence up to 9
}
return 0;
}

Output
The calculated Fibonacci sequence would be:
0 1 1 2 3 5 8 13 21 34

You might also like