🧩 Functions in C
Functions are one of the most important building blocks of C programming. They allow us to divide a large program into smaller, meaningful and reusable pieces of code.
A function is a named block of code designed to perform a particular task. Instead of writing the same logic repeatedly, we can place it inside a function and call that function whenever required.
11.1 What Is a Function?
A function is a block of statements that performs a specific operation. It can receive input through parameters and can optionally return a result.
#include <stdio.h>
void greet(void)
{
printf("Hello, CodeBhavya!\n");
}
int main(void)
{
greet();
return 0;
}
Here, greet() is a user-defined function.
When greet() is called, the statements inside its body execute.
greet
void
void — no parameters
The statements inside { }
11.2 Why Do We Need Functions?
Imagine a program that contains 2,000 lines of code.
If all of those statements are written inside main(),
the program becomes difficult to read, test and maintain.
Functions allow us to divide the program according to responsibilities.
main()
{
input code
calculation code
validation code
display code
another calculation
another validation
another display
}
With functions:
main()
{
readData();
calculateResult();
validateResult();
displayResult();
}
Write logic once and call it multiple times.
Function names explain what different parts of a program do.
Individual functions can be tested separately.
Changes can often be isolated to one function.
11.3 Anatomy of a Function
return_type function_name(parameter_list)
{
// function body
statements;
return value;
}
A function can be understood through four major parts:
| Part | Meaning | Example |
|---|---|---|
| Return type | Type of value returned by the function | int |
| Function name | Name used to call the function | add |
| Parameters | Inputs received by the function | int a, int b |
| Function body | Statements executed when called | { ... } |
11.4 Function Declaration
A function declaration tells the compiler about a function before the function is used.
int add(int a, int b);
This tells the compiler that a function named add:
- returns an
int - expects two
intparameters - will be defined somewhere in the program
A function declaration is also commonly called a function prototype.
11.5 Function Definition
The function definition contains the actual implementation.
int add(int a, int b)
{
return a + b;
}
The definition tells the compiler what the function actually does.
| Declaration | Definition |
|---|---|
| Tells what the function looks like | Contains the implementation |
Usually ends with ; |
Contains a function body |
int add(int, int); |
int add(int a, int b) { ... } |
11.6 Calling a Function
A function does not execute merely because it has been defined. It executes when it is called.
#include <stdio.h>
void message(void)
{
printf("Welcome to C Programming!\n");
}
int main(void)
{
message();
return 0;
}
The statement:
message();
is the function call.
Program flow
main()
|
| calls
v
message()
|
| executes printf()
v
returns to main()
|
v
return 0
11.7 Parameters and Arguments
Functions can receive data from the caller. The variables listed in the function definition are called parameters. The actual values supplied during the call are called arguments.
int add(int a, int b)
{
return a + b;
}
int result = add(10, 20);
| Term | Example | Meaning |
|---|---|---|
| Parameter | int a |
Variable receiving a value |
| Parameter | int b |
Variable receiving a value |
| Argument | 10 |
Actual value supplied by caller |
| Argument | 20 |
Actual value supplied by caller |
11.8 Returning a Value
A function can calculate a result and send that result back to its caller
using the return statement.
int square(int n)
{
return n * n;
}
int main(void)
{
int result;
result = square(5);
printf("%d\n", result);
return 0;
}
Execution:
square(5)
|
| n = 5
|
| 5 * 5
v
return 25
|
v
result = 25
The value returned by a function can be stored in a variable, printed, used in another expression, or passed to another function.
11.9 Functions That Return Nothing — void
If a function does not return a value, its return type can be
void.
void display(void)
{
printf("Hello!\n");
}
The first void means the function returns no value.
The second void means it accepts no parameters.
void display(void);
| Declaration | Meaning |
|---|---|
void display(void); |
No return value and no parameters |
void display(int n); |
No return value, one integer parameter |
int display(void); |
Returns an integer, no parameters |
11.10 Functions with Multiple Parameters
A function can receive multiple parameters.
int multiply(int a, int b, int c)
{
return a * b * c;
}
int main(void)
{
int result = multiply(2, 3, 4);
printf("%d\n", result);
return 0;
}
The values are matched with parameters according to their position:
multiply(2, 3, 4)
a = 2
b = 3
c = 4
The number, order and compatible types of arguments should match the function's parameter list.
11.11 Why Do We Need a Function Prototype?
Suppose the function is defined after main().
The compiler needs to know about the function before encountering the
call.
#include <stdio.h>
int add(int a, int b);
int main(void)
{
int result = add(10, 20);
printf("%d\n", result);
return 0;
}
int add(int a, int b)
{
return a + b;
}
The prototype:
int add(int a, int b);
provides the necessary information before the call.
Prototype
|
v
Compiler knows function signature
|
v
main() calls add()
|
v
add() definition appears later
|
v
Function executes
11.12 Defining a Function Before main()
A function can also be completely defined before main().
In that case, the compiler has already seen the definition when it
encounters the call.
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main(void)
{
printf("%d\n", add(5, 7));
return 0;
}
Prototype first, definition later.
Definition first, then main().
11.13 Library Functions vs User-Defined Functions
| Library Function | User-Defined Function |
|---|---|
| Provided by C libraries | Created by the programmer |
printf() |
calculateTotal() |
scanf() |
findMaximum() |
strlen() |
isPrime() |
For example, printf() is a library function provided through
the standard I/O facilities, while add() in the following
program is user-defined.
int add(int a, int b)
{
return a + b;
}
11.14 C Uses Pass-by-Value
C passes function arguments by value. That means the function receives a value for its parameter. Changing that parameter does not directly change the caller's ordinary variable.
#include <stdio.h>
void change(int x)
{
x = 100;
}
int main(void)
{
int n = 10;
change(n);
printf("%d\n", n);
return 0;
}
Output:
10
main()
n = 10
|
| value copied
v
change()
x = 10
|
| x = 100
v
x = 100
Back in main:
n is still 10
C does not have a separate "call by reference" parameter mechanism like some languages. C programs commonly achieve modification of caller data by passing addresses through pointers.
11.15 Local Variables Inside Functions
A variable declared inside a function normally has block scope and can be accessed only within the appropriate block.
void calculate(void)
{
int total = 50;
printf("%d\n", total);
}
The variable total is local to the function.
void calculate(void)
{
int total = 50;
}
int main(void)
{
printf("%d", total); /* Error */
}
total is not visible in main().
11.16 Functions and Global Variables
A variable defined outside functions can have file scope and may be accessible to functions in the same source file according to its declaration and linkage.
#include <stdio.h>
int count = 10;
void display(void)
{
printf("%d\n", count);
}
int main(void)
{
display();
return 0;
}
Global variables can be useful in specific situations, but excessive use of global mutable state can make programs harder to understand and test. Prefer passing required data through function parameters when practical.
11.17 Passing an Array to a Function
Arrays are frequently processed using functions. When an array is passed to a function, the parameter is adjusted to a pointer to its first element.
#include <stdio.h>
void display(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
}
int main(void)
{
int numbers[] = {10, 20, 30, 40};
display(numbers, 4);
return 0;
}
Inside the function, the parameter arr is not a complete
array object. Therefore sizeof(arr) inside the function
does not give the original array size.
11.18 Passing Strings to Functions
A C string is stored in a character array ending with the null character
'\0'.
A string can be passed to a function using a character pointer or an
array parameter.
#include <stdio.h>
void displayString(const char text[])
{
printf("%s\n", text);
}
int main(void)
{
char name[] = "CodeBhavya";
displayString(name);
return 0;
}
The const qualifier communicates that the function does not
intend to modify the characters through that parameter.
11.19 Functions and Pointers — Preview
Pointers allow a function to work with the address of an object. This is how a function can modify a variable belonging to its caller.
#include <stdio.h>
void change(int *x)
{
*x = 100;
}
int main(void)
{
int n = 10;
change(&n);
printf("%d\n", n);
return 0;
}
Here:
&n → address of n
*x → value stored at that address
Pointers will be studied in detail in the dedicated Pointers topic. For now, remember that passing an address gives a function access to the same object.
11.20 Recursion
Recursion occurs when a function calls itself.
void countDown(int n)
{
if (n == 0)
{
return;
}
printf("%d\n", n);
countDown(n - 1);
}
A recursive function normally needs two important parts:
The condition that stops recursion.
The part that calls the function again.
The recursive calls may continue until the program exhausts available stack space, resulting in undefined behavior or abnormal termination.
11.21 Program Tracing — Recursive Function
Consider:
void countDown(int n)
{
if (n == 0)
return;
printf("%d ", n);
countDown(n - 1);
}
Suppose:
countDown(3);
The execution can be visualized as:
countDown(3)
|
| print 3
v
countDown(2)
|
| print 2
v
countDown(1)
|
| print 1
v
countDown(0)
|
| base case
v
return
Output:
3 2 1
When a function calls another function, the current function's execution is paused until the called function returns. For recursion, this creates a chain of active function calls.
11.22 Function Calls and the Call Stack
When a function is called, the program needs to keep track of the function's execution state, parameters and local information. This is commonly represented using the call stack.
main()
|
+--> calculate()
|
+--> square()
|
+--> return
|
+--> return
|
+--> return
TOP
┌──────────────────────┐
│ square() │
├──────────────────────┤
│ calculate() │
├──────────────────────┤
│ main() │
└──────────────────────┘
BOTTOM
When square() returns, its active call is removed and
execution continues in calculate().
11.23 One Function Can Call Another Function
#include <stdio.h>
int square(int n)
{
return n * n;
}
int doubleValue(int n)
{
return 2 * n;
}
int main(void)
{
int value = square(doubleValue(3));
printf("%d\n", value);
return 0;
}
Trace the calls from the inside:
doubleValue(3)
↓
6
square(6)
↓
36
value = 36
For nested function calls, identify which function must produce a value first.
Draw the call chain when the expression looks complicated.
11.24 Designing Good Functions
A good function generally has a clear responsibility.
| Less Clear | Better Decomposition |
|---|---|
One huge main() |
readInput() |
| Mixed calculation and display | calculateTotal() |
| Repeated validation logic | isValid() |
| Repeated searching logic | findMaximum() |
Input
↓
Validation
↓
Calculation
↓
Output
Each responsibility can potentially become a separate function.
11.25 Common Mistakes
1. Calling a function with the wrong number of arguments
int add(int a, int b);
add(10); /* Wrong */
add(10, 20); /* Correct */
2. Forgetting the return statement
int square(int n)
{
n * n; /* Does not return the result */
}
Correct:
int square(int n)
{
return n * n;
}
3. Returning a value from a void function
void display(void)
{
return 10; /* Wrong */
}
4. Using a local variable outside its scope
void test(void)
{
int x = 10;
}
int main(void)
{
printf("%d", x); /* Wrong */
}
5. Infinite recursion
void test(void)
{
test();
}
There is no terminating condition.
6. Modifying a variable incorrectly through a value parameter
void change(int x)
{
x = 100;
}
This does not modify the caller's ordinary variable.
11.26 Common Confusions
Function declaration vs function call
int add(int, int); /* declaration */
add(10, 20); /* call */
Parameter vs argument
int add(int a, int b)
{
return a + b;
}
add(5, 7);
a and b are parameters.
5 and 7 are arguments.
Return value vs printing
int square(int n)
{
return n * n;
}
Returning a value and printing a value are different operations.
void parameter list
void display(void)
This explicitly means that the function accepts no parameters.
11.27 Complete Program Analysis
#include <stdio.h>
int calculateSquare(int n);
int main(void)
{
int number;
int result;
printf("Enter a number: ");
scanf("%d", &number);
result = calculateSquare(number);
printf("Square = %d\n", result);
return 0;
}
int calculateSquare(int n)
{
return n * n;
}
Execution flow
1. Program starts
↓
2. main() begins
↓
3. number is declared
↓
4. Input is read
↓
5. calculateSquare(number) is called
↓
6. value is copied into n
↓
7. n * n is calculated
↓
8. result is returned
↓
9. result receives returned value
↓
10. printf() displays result
↓
11. return 0
↓
12. Program ends
11.28 Four Common Function Forms
A useful beginner classification is based on whether a function receives arguments and whether it returns a value.
| Type | Example |
|---|---|
| No arguments, no return value | void display(void) |
| Arguments, no return value | void display(int n) |
| No arguments, returns value | int getNumber(void) |
| Arguments and returns value | int add(int a, int b) |
Ask two questions:
- Does the function receive data?
- Does the function return data?
Those two answers help identify the function form.
11.29 Important Interview Point: Array Parameter
Consider:
void display(int arr[])
For a function parameter, an array parameter is adjusted to a pointer parameter. Therefore, these forms are equivalent for parameter purposes:
void display(int arr[]);
void display(int *arr);
The array's size is therefore commonly passed separately:
void display(int arr[], int size)
"An array is completely copied when passed to a function."
Better explanation:For a function parameter, an array parameter is adjusted to a pointer to its first element, so the function can access the original array elements.
11.30 Quick Revision
Reusable block of code for a particular task.
Declares a function before its use.
Variable listed in a function definition.
Actual value supplied during a call.
Sends a value back to the caller.
Represents no value in relevant function contexts.
A function calling itself.
C passes argument values to parameters.
🧠 Test Your Understanding
🎯 Interview Preparation
1. What is a function in C?
A function is a named block of code that performs a particular task. It may receive parameters and may return a value.
2. What is a function prototype?
A function prototype declares the function's return type, name and parameter types before the function is used.
3. What is call by value?
C passes argument values to function parameters. The parameter is therefore a separate object/value from the caller's ordinary variable.
4. How can a function modify a caller's variable?
By passing its address to the function and using a pointer parameter.
5. What is recursion?
Recursion occurs when a function directly or indirectly calls itself. A terminating condition is required.
6. Can a function return multiple values directly?
A function has one return value expression. Multiple pieces of information can be returned through pointers, structures, or other suitable designs.
7. Can a function return an array directly?
A function cannot return an array type directly. Other techniques such as returning a pointer to suitable storage or returning a structure can be used depending on the problem.
💼 Placement Tips
For function-based questions, first identify the order in which functions are called.
Follow exactly where each returned value is stored or used.
A local variable belongs to its appropriate block and cannot automatically be used elsewhere.
Remember that C passes arguments by value.
Always identify the base case before tracing recursive calls.
Remember that an array parameter is adjusted to a pointer parameter.
11.31 Function Practice Problems
Solve these problems using user-defined functions. Try the problem yourself before opening the solution.
Problem 1 — Add Two Numbers Using a Function
Not Started
Read two integers and create a function add() that returns
their sum.
int add(int a, int b)
Then return a + b.
Your Program
Input
Expected Output
30
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main(void)
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", add(a, b));
return 0;
}
Problem 2 — Find the Larger Number
Not Started
Create a function maximum() that receives two integers and
returns the larger value.
if condition inside the function.
Your Program
Input
Expected Output
25
#include <stdio.h>
int maximum(int a, int b)
{
if (a > b)
return a;
return b;
}
int main(void)
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", maximum(a, b));
return 0;
}
Problem 3 — Check Even or Odd
Not Started
Create a function isEven() that returns 1 when
the supplied integer is even and 0 otherwise.
n % 2
Your Program
Input
Expected Output
1
#include <stdio.h>
int isEven(int n)
{
return n % 2 == 0;
}
int main(void)
{
int n;
scanf("%d", &n);
printf("%d\n", isEven(n));
return 0;
}
Problem 4 — Calculate Square and Cube
Not Started
Create two functions: square() and cube().
Read one integer and print both results.
Your Program
Input
Expected Output
Square = 16 Cube = 64
#include <stdio.h>
int square(int n)
{
return n * n;
}
int cube(int n)
{
return n * n * n;
}
int main(void)
{
int n;
scanf("%d", &n);
printf("Square = %d\n", square(n));
printf("Cube = %d\n", cube(n));
return 0;
}
Problem 5 — Sum from 1 to N Using a Function
Not Started
Create a function sumToN() that receives a positive integer
n and returns the sum of all integers from 1
through n.
sum = 0;
for (...)
{
sum += i;
}
Your Program
Input
Expected Output
55
#include <stdio.h>
int sumToN(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
int main(void)
{
int n;
scanf("%d", &n);
printf("%d\n", sumToN(n));
return 0;
}
11.32 Challenge Yourself
Try these without looking at the solution:
- Write a function to find the minimum of three integers.
- Write a function that counts the number of digits in an integer.
- Write a function to calculate the factorial of a number.
- Write a recursive function to calculate factorial.
- Write a function that checks whether a number is prime.
- Write a function that reverses an integer.
- Write a function that calculates the sum of array elements.
- Write a function that finds the maximum element of an array.
- Write a function that counts vowels in a string.
- Write a function that checks whether a string is a palindrome.
Given an array of integers, create separate functions to calculate:
- sum
- average
- maximum
- minimum
- number of even elements
- number of odd elements
Keep main() responsible mainly for input, function calls and
displaying results.
⭐ Key Takeaway
Functions divide a program into reusable units.
A function can receive data through parameters, perform an operation, and optionally return a result to its caller.
Input
↓
Function Call
↓
Parameters receive values
↓
Function executes
↓
Return value
↓
Caller continues
Mastering functions is essential before moving deeply into pointers, structures, dynamic memory and larger C programs.