What is Functions in C Programming: Complete Guide to Function Declaration, Definition, Calling & Examples Program

Chapter 13: Functions

Previous Chapter | Current Chapter: Functions | Next Chapter

Author: Er. Mujtaba Ansari

Functions make C programs very simple, organized, reusable, readable, and easier to maintain.

Real-Life Uses: Functions are used in operating systems, banking software, games, embedded systems, calculators, automation, and mobile applications to perform specific tasks efficiently.

Functions are one of the most important concepts in C programming. They help us divide a large program into smaller, logical, and reusable blocks of code.

Using functions, a program becomes easier to understand, write, test, debug, reuse, and maintain.

In this chapter, you will learn functions in C from basic concepts to advanced topics, including function declaration, definition, calling, parameters, arrays, strings, recursion, nested function calls, and passing values using pointers.

A function is a block or group of statements that are logically related and perform a specific task.

A function can also return a value after performing its operation.

Simple Example

Suppose you want to calculate the sum of two numbers.

Instead of writing the same calculation repeatedly, you can create a function:

int sum(int a, int b)
{
    return a + b;
}

You can then call this function whenever you need to calculate a sum.

Functions make programs:

  • Simple and organized
  • Easy to understand
  • Reusable
  • Easier to debug
  • Easier to maintain
  • Less repetitive

Functions in C are mainly divided into two types:

1. Predefined or Library Functions

These functions are already provided by the C standard library.

Examples:

printf()
scanf()
strlen()
strcpy()
sqrt()

For example:

printf("Hello World");

Here, printf() is a library function.

2. User-Defined Functions

A function created and defined by the programmer is called a user-defined function.

Example:

int sum(int a, int b)
{
    return a + b;
}

Here, sum() is a user-defined function.

A user-defined function generally involves three main steps:

  1. Function Declaration or Prototype
  2. Function Definition
  3. Function Call

1. Function Declaration / Prototype

A function prototype tells the compiler about the function before it is used.

It specifies:

  • Function name
  • Return type
  • Number of parameters
  • Type of parameters
Syntax
return_type function_name(parameter_list);
Example
int sum(int x, int y);

This tells the compiler that:

  • Function name is sum
  • It returns an int
  • It accepts two int parameters

2. Function Definition

The function definition contains the actual statements that perform the required task.

Syntax
return_type function_name(parameter_list)
{
    // Function body

    return value;
}
Example
int sum(int x, int y)
{
    int result;

    result = x + y;

    return result;
}

3. Function Call

A function call is used to execute a function.

Example:

result = sum(10, 20);

Here, sum() is called with two arguments.

#include <stdio.h>

int sum(int x, int y);

int main(void)
{
    int result;

    result = sum(10, 20);

    printf("Sum = %d\n", result);

    return 0;
}

int sum(int x, int y)
{
    return x + y;
}
Output
Sum = 30

The values passed to a function are called arguments.

The variables that receive those values inside the function are called parameters.

Example:

sum(10, 20);

Here, 10 and 20 are arguments.

In:

int sum(int x, int y)

x and y are parameters.

The factorial of a positive integer N is:

N! = N × (N-1) × (N-2) × ... × 1

For example:

3! = 3 × 2 × 1 = 6
#include <stdio.h>

unsigned long long factorial(int n);

int main(void)
{
    int n;
    unsigned long long result;

    printf("Enter a number: ");
    scanf("%d", &n);

    if (n < 0)
    {
        printf("Factorial is not defined for negative numbers.\n");
        return 0;
    }

    result = factorial(n);

    printf("Factorial = %llu\n", result);

    return 0;
}

unsigned long long factorial(int n)
{
    unsigned long long fact = 1;
    int i;

    for (i = 1; i <= n; i++)
    {
        fact = fact * i;
    }

    return fact;
}
Example

For:

N = 3

Calculation:

1 × 2 × 3 = 6

Output:

Factorial = 6

A function can also be used to calculate the sum of a mathematical series.

For example:

1 + X + X² + X³ + ... + Xᴺ
#include <stdio.h>

long long seriesSum(int n, int x);

int main(void)
{
    int n, x;
    long long result;

    printf("Enter N: ");
    scanf("%d", &n);

    printf("Enter X: ");
    scanf("%d", &x);

    result = seriesSum(n, x);

    printf("Series Sum = %lld\n", result);

    return 0;
}

long long seriesSum(int n, int x)
{
    long long sum = 0;
    long long term = 1;
    int i;

    for (i = 0; i <= n; i++)
    {
        sum += term;
        term *= x;
    }

    return sum;
}

For:

N = 3
X = 4

The series is:

1 + 4 + 16 + 64 = 85

So:

Series Sum = 85

Note: If your intended series is X + X² + ... + Xᴺ, the starting term should be changed accordingly.

Arrays can be passed to functions.

This is useful when we want a function to process multiple values.

For example, we can create a function to find the largest element in an array.

#include <stdio.h>

int largest(int arr[], int n);

int main(void)
{
    int arr[20];
    int n, i, result;

    printf("Enter number of elements: ");
    scanf("%d", &n);

    if (n <= 0 || n > 20)
    {
        printf("Invalid number of elements.\n");
        return 0;
    }

    printf("Enter %d elements:\n", n);

    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }

    result = largest(arr, n);

    printf("Largest element = %d\n", result);

    return 0;
}

int largest(int arr[], int n)
{
    int i;
    int max = arr[0];

    for (i = 1; i < n; i++)
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }
    }

    return max;
}
Important Point for YOU:

Array indexing starts from 0.

Therefore, if an array contains n elements, the valid indexes are:

0 to n-1

So the loop should use:

i < n

not:

i <= n

Two-dimensional arrays can also be passed to functions.

For example, consider a 3 × 3 matrix.

We can create a function to print its lower triangular portion.

#include <stdio.h>

void lower(int arr[][3]);

int main(void)
{
    int arr[3][3];
    int i, j;

    printf("Enter 9 elements of the matrix:\n");

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            scanf("%d", &arr[i][j]);
        }
    }

    printf("\nLower triangular matrix:\n");

    lower(arr);

    return 0;
}

void lower(int arr[][3])
{
    int i, j;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            if (j <= i)
            {
                printf("%d ", arr[i][j]);
            }
            else
            {
                printf("  ");
            }
        }

        printf("\n");
    }
}
Example

For:

1 2 3
4 5 6
7 8 9

The lower triangular portion is:

1
4 5
7 8 9

String concatenation means joining two strings together.

For example:

Hello + World

becomes:

HelloWorld
#include <stdio.h>
#include <string.h>

void concat(char x[], const char y[]);

int main(void)
{
    char a[50];
    char b[25];

    printf("Enter first string: ");
    fgets(a, sizeof(a), stdin);

    printf("Enter second string: ");
    fgets(b, sizeof(b), stdin);

    a[strcspn(a, "\n")] = '\0';
    b[strcspn(b, "\n")] = '\0';

    concat(a, b);

    printf("Concatenated string = %s\n", a);

    return 0;
}

void concat(char x[], const char y[])
{
    int i = 0;
    int j = 0;

    while (x[i] != '\0')
    {
        i++;
    }

    while (y[j] != '\0')
    {
        x[i] = y[j];
        i++;
        j++;
    }

    x[i] = '\0';
}
Important Note:

The destination array must have enough space to store both strings.

A string can also be copied using a user-defined function.

#include <stdio.h>
#include <string.h>

void copyString(char destination[], const char source[]);

int main(void)
{
    char source[50];
    char destination[50];

    printf("Enter a string: ");
    fgets(source, sizeof(source), stdin);

    source[strcspn(source, "\n")] = '\0';

    copyString(destination, source);

    printf("Copied string = %s\n", destination);

    return 0;
}

void copyString(char destination[], const char source[])
{
    int i = 0;

    while (source[i] != '\0')
    {
        destination[i] = source[i];
        i++;
    }

    destination[i] = '\0';
}
Important Difference

Copying:

Source → Destination

Concatenation:

String 1 + String 2 → Combined String

When one function calls another function, it is commonly described as a nested function call.

Example:

main()
   ↓
sum()
   ↓
square()

or:

main()
   ↓
sum()
   ↓
cube()
Important Technical Point for YOU:

Standard C does not allow defining one function inside another function.

However, one function can call another function.

#include <stdio.h>

int square(int n);
int cube(int n);
int sum(int n);

int main(void)
{
    int n;
    int result;

    printf("Enter a number: ");
    scanf("%d", &n);

    result = sum(n);

    printf("Sum of square and cube = %d\n", result);

    return 0;
}

int square(int n)
{
    return n * n;
}

int cube(int n)
{
    return n * n * n;
}

int sum(int n)
{
    return square(n) + cube(n);
}

For:

N = 3

Calculation:

Square = 3² = 9
Cube = 3³ = 27

Sum = 9 + 27 = 36

Recursion is a programming technique in which a function calls itself.

A recursive function must have a condition that stops further function calls.

A recursive function normally contains two important parts:

1. Base Case

The condition that stops recursion.

2. Recursive Case

The part where the function calls itself.

return_type function()
{
    if (base_condition)
    {
        return value;
    }

    return function();
}

The factorial formula is:

N! = N × (N-1)!

The base case is:

0! = 1
#include <stdio.h>

unsigned long long factorial(int n);

int main(void)
{
    int n;

    printf("Enter a number: ");
    scanf("%d", &n);

    if (n < 0)
    {
        printf("Factorial is not defined for negative numbers.\n");
        return 0;
    }

    printf("Factorial = %llu\n", factorial(n));

    return 0;
}

unsigned long long factorial(int n)
{
    if (n == 0 || n == 1)
    {
        return 1;
    }

    return (unsigned long long)n * factorial(n - 1);
}
Working

For:

factorial(3)

The calls are:

3 × factorial(2)
        ↓
      2 × factorial(1)
              ↓
                1

Therefore:

3 × 2 × 1 = 6

The GCD or HCF is the greatest number that divides two numbers without leaving a remainder.

The Euclidean algorithm uses:

GCD(a, b) = GCD(b, a % b)

until the remainder becomes zero.

#include <stdio.h>
#include <stdlib.h>

long long gcd(long long a, long long b);

int main(void)
{
    long long x, y;
    long long g, lcm;

    printf("Enter two numbers: ");
    scanf("%lld %lld", &x, &y);

    if (x == 0 && y == 0)
    {
        printf("GCD and LCM are undefined for 0 and 0.\n");
        return 0;
    }

    g = gcd(llabs(x), llabs(y));

    if (x == 0 || y == 0)
    {
        lcm = 0;
    }
    else
    {
        lcm = llabs((x / g) * y);
    }

    printf("GCD/HCF = %lld\n", g);
    printf("LCM = %lld\n", lcm);

    return 0;
}

long long gcd(long long a, long long b)
{
    if (b == 0)
    {
        return a;
    }

    return gcd(b, a % b);
}
Example

For:

X = 12
Y = 18

GCD:

GCD(12,18)
→ GCD(18,12)
→ GCD(12,6)
→ GCD(6,0)
→ 6

Therefore:

GCD = 6
LCM = 36

The sum of squares is:

1² + 2² + 3² + ... + N²
#include <stdio.h>

long long sumSquares(int n);

int main(void)
{
    int n;

    printf("Enter N: ");
    scanf("%d", &n);

    if (n < 0)
    {
        printf("Please enter a non-negative number.\n");
        return 0;
    }

    printf("Sum of squares = %lld\n", sumSquares(n));

    return 0;
}

long long sumSquares(int n)
{
    if (n == 0)
    {
        return 0;
    }

    return (long long)n * n + sumSquares(n - 1);
}

For:

N = 3

Calculation:

1² + 2² + 3²
= 1 + 4 + 9
= 14

The Fibonacci sequence is commonly defined as:

0 1 1 2 3 5 8 13 ...

The formula is:

F(n) = F(n-1) + F(n-2)

with:

F(0) = 0
F(1) = 1
#include <stdio.h>

int fibonacci(int n);

int main(void)
{
    int n, i;

    printf("Enter number of terms: ");
    scanf("%d", &n);

    if (n <= 0)
    {
        printf("Please enter a positive number.\n");
        return 0;
    }

    printf("Fibonacci Series: ");

    for (i = 0; i < n; i++)
    {
        printf("%d ", fibonacci(i));
    }

    printf("\n");

    return 0;
}

int fibonacci(int n)
{
    if (n == 0)
    {
        return 0;
    }

    if (n == 1)
    {
        return 1;
    }

    return fibonacci(n - 1) + fibonacci(n - 2);
}
Example

For 7 terms:

0 1 1 2 3 5 8

Note: Some textbooks start the Fibonacci series with 1 1 2 3 5.... Both conventions are used, but the program above follows the standard programming definition starting with 0, 1.

Arguments can be passed to functions in different ways.

Two commonly discussed methods are:

  1. Pass by Value
  2. Pass by Address using Pointers

In call by value, a copy of the actual value is passed to the function.

Changes made to the parameter inside the function do not change the original variable.

Example:
void change(int x)
{
    x = 100;
}

If we call:

int a = 10;

change(a);

The value of a remains:

10

because only a copy of a was passed.

#include <stdio.h>

void swap(int p, int q);

int main(void)
{
    int a = 10;
    int b = 20;

    printf("Before function call:\n");
    printf("A = %d, B = %d\n", a, b);

    swap(a, b);

    printf("\nAfter function call:\n");
    printf("A = %d, B = %d\n", a, b);

    return 0;
}

void swap(int p, int q)
{
    int temp;

    temp = p;
    p = q;
    q = temp;

    printf("\nInside function:\n");
    printf("P = %d, Q = %d\n", p, q);
}
Output Concept:

Inside the function, the values are swapped.

However, the original variables in main() remain unchanged.

This happens because C passes arguments by value.

C does not have true call-by-reference parameters like some other programming languages.

Instead, C passes arguments by value, but we can pass the address of a variable using a pointer.

This allows the function to modify the original variable.

This is commonly called:

  • Call by Address
  • Passing by Address
  • Pointer-based parameter passing
#include <stdio.h>

void swap(int *p, int *q);

int main(void)
{
    int a = 10;
    int b = 20;

    printf("Before swapping:\n");
    printf("A = %d, B = %d\n", a, b);

    swap(&a, &b);

    printf("\nAfter swapping:\n");
    printf("A = %d, B = %d\n", a, b);

    return 0;
}

void swap(int *p, int *q)
{
    int temp;

    temp = *p;
    *p = *q;
    *q = temp;
}
Output
Before swapping:
A = 10, B = 20

After swapping:
A = 20, B = 10

Here:

&a

means the address of a.

And:

*p

means the value stored at the address held by p.

Functions can commonly be classified according to whether they accept arguments and return a value.

1. No Arguments and No Return Value

void display(void)
{
    printf("Hello");
}

2. Arguments but No Return Value

void display(int n)
{
    printf("%d", n);
}

3. No Arguments but Returns a Value

int getNumber(void)
{
    return 10;
}

4. Arguments and Returns a Value

int sum(int a, int b)
{
    return a + b;
}

The fourth type is very commonly used in real programs.

Local Variable

A variable declared inside a function or block is called a local variable.

Example:

void test(void)
{
    int x = 10;
}

x can normally be accessed only within its scope.

Global Variable

A variable declared outside all functions is called a global variable.

Example:

int count = 0;

int main(void)
{
    printf("%d", count);
    return 0;
}

Global variables can be accessed by multiple functions within their scope.

Best Practice for YOU:

Prefer local variables whenever possible because they make programs easier to understand and maintain.

RecursionIteration
Function calls itselfLoop repeats statements
Uses function-call stackUsually uses less memory
Can make some problems easier to expressOften more efficient
Requires a base caseRequires a loop condition
Useful for tree and divide-and-conquer problemsUseful for repetitive calculations

Example of iteration:

for (i = 1; i <= n; i++)
{
    printf("%d ", i);
}

Example of recursion:

void print(int n)
{
    if (n == 0)
        return;

    print(n - 1);
}

Mistake 1: Forgetting the Function Prototype

If a function is used before its definition, declare its prototype first.

int sum(int, int);

Mistake 2: Incorrect Return Type

If a function returns an integer, its return type should be appropriate.

int sum(int a, int b)
{
    return a + b;
}

Mistake 3: Using <= Instead of < for Arrays

Incorrect:

for (i = 0; i <= n; i++)

Correct:

for (i = 0; i < n; i++)

Mistake 4: Forgetting the Base Case in Recursion

A recursive function must eventually stop.

Without a proper base case, the program may continue calling the function until the stack is exhausted.

Mistake 5: Confusing Copy and Concatenation

Copying replaces the destination content.

Concatenation joins two strings.

Mistake 6: Using gets()

The old gets() function is unsafe and should not be used.

Use:

fgets()

instead.

Older C programming examples often contain:

#include <conio.h>
clrscr();
getch();
void main()

These are commonly seen in old Turbo C-based textbooks.

For modern C programming, prefer:

#include <stdio.h>

int main(void)
{
    return 0;
}

Also use standard functions such as:

fgets()

instead of unsafe input functions such as:

gets()

Functions are used everywhere in software development.

Examples include:

Banking Software

Functions can handle:

deposit()
withdraw()
checkBalance()
transferMoney()

Calculator Applications

Functions can perform:

addition()
subtraction()
multiplication()
division()

Games

Functions can handle:

movePlayer()
calculateScore()
checkCollision()
updateGame()

Operating Systems

Functions perform tasks related to:

memory management
file operations
process management
device handling

Embedded Systems

Functions are used for:

sensor reading
motor control
display control
communication

Advantages of Functions

Functions provide several important advantages:

  1. Code Reusability
    Write once and use multiple times.
  2. Modularity
    Large programs can be divided into smaller parts.
  3. Easy Debugging
    Individual functions can be tested separately.
  4. Better Readability
    Functions make code easier to understand.
  5. Easy Maintenance
    Changes can often be made in one function instead of many places.
  6. Reduced Code Duplication
    Repeated logic can be placed inside a function.

What is a Function?

A function is a reusable block of code designed to perform a specific task.

Types of Functions

1. Library Functions
2. User-Defined Functions

Three Main Steps

1. Declaration
2. Definition
3. Function Call

Recursion

A function calling itself is called recursion.

Two Important Cases in Recursion

1. Base Case
2. Recursive Case

Passing Arguments

Call by Value
Call by Address using Pointers

Four Common Function Forms

1. No arguments, no return value
2. Arguments, no return value
3. No arguments, return value
4. Arguments, return value

writing the following programs using functions:

  1. Find the sum of two numbers.
  2. Find the largest of three numbers.
  3. Find the smallest element in an array.
  4. Calculate factorial using a function.
  5. Calculate factorial using recursion.
  6. Check whether a number is prime.
  7. Print prime numbers within a range.
  8. Find the GCD of two numbers.
  9. Find the LCM of two numbers.
  10. Generate the Fibonacci series.
  11. Find the sum of squares of the first N natural numbers.
  12. Reverse a string using a function.
  13. Check whether a string is a palindrome.
  14. Copy one string to another.
  15. Concatenate two strings.
  16. Find the length of a string without using strlen().
  17. Find the largest element of an array.
  18. Sort an array using a function.
  19. Add two matrices using a function.
  20. Swap two numbers using pointers.

What is a function in C?

A function is a reusable block of statements that performs a specific task.

Why are functions used in C?

Functions make programs modular, reusable, readable, and easier to maintain.

What is a user-defined function?

A function created and defined by the programmer is called a user-defined function.

What is a function prototype?

A function prototype informs the compiler about the function’s name, return type, and parameters.

What is recursion?

Recursion is a technique where a function calls itself.

What is a base case?

A base case is the condition that stops recursive function calls.

Does C support call by reference?

C does not provide true call-by-reference parameters. C uses pass-by-value. However, pointers can be used to pass addresses and modify the original variables.

Can arrays be passed to functions?

Yes. Arrays can be passed to functions, allowing the function to process their elements.

Can strings be passed to functions?

Yes. Since strings are character arrays in C, they can be passed to functions using character-array parameters or pointers.



Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top